github varabyte/kobweb v0.13.12

latest releases: v0.24.0, v0.23.3, v0.23.2...
2 years ago

The big feature with this release is the new Checkbox Silk widget:

silk-checkboxes.mp4

As you can see, checkboxes are fairly configurable -- you can tweak their size, their colors, and even their icons.

Checkboxes use an API inspired by Android Jetpack Compose. At their simplest, the code looks like:

var checked by remember { mutableStateOf(true) }
Checkbox(checked, onCheckedChange = { checked = it })

While Checkbox works with a simple "on / off" concept, TriCheckbox is used for checkboxes that can be on, off, or indeterminate. The "Parent" checkbox in the video above is a TriCheckbox. They work very similar to a normal Checkbox:

var checked by remember { mutableStateOf(CheckedState.Indeterminate) }
TriCheckbox(checked, onCheckedChange = { checked = it })

Silk

  • New Checkbox widget
  • New Label widget
    • Labels are a way you can associate text with HTML form controls (currently Switches, Checkboxes, and Inputs).
    • Once bound, screen readers can tie label text with the control; also, clicking on a label will affect the target element it is tied to.
    • Note that labels only work with special form elements. Tying a label to some random element, say a div, will have no effect.
  • Began adding some initial SVG icons that projects can use, especially useful if you don't want to pull in large dependencies like Font Awesome or Material Design Icons.

Frontend

  • setTimeout and setInterval methods have been migrated to use the idiomatic Kotlin Duration class instead of raw millisecond values
  • Added Modifier.textTransform
  • Made improvements to SVG element APIs
    • All SVG children types (e.g. rectangles, circles, paths, polygons, etc.) are now supported (although the Compose HTML SVG bindings are still fairly barren; we added #307 for now to make sure we address improving this situation via extension methods before 1.0)
  • Added some file util methods around reading file bytes
  • Added some element util methods have been added to Kobweb
    • descendantsBfs, descedantsDfs, and ancestors sequences are provided to make it trivial to walk a DOM tree in either direction from some element.
    • generateUniqueId allows you to generate a random ID that you can safely set on any element without worrying about an ID conflict.

Backend

  • The ApiStream factory method that accepts a route override is deprecated. Instead, tag your object with an @Api annotation.
    • It's unlikely any users are even using this, but if you were, sorry! This change is necessary as we prepare to migrate some of our Gradle logic over to KSP.
       // Before
       val echo = ApiStream("echo") { ... }
       // After
       @Api("echo")
       val echo = ApiStream { ... }

Notes

CheckedState

With TriCheckbox and CheckedState, you are often trying to determine if some parent checkbox should be checked, unchecked, or indeterminate based on children boolean values. CheckedState makes this easy by providing from and toBoolean conversions for you:

var child1Checked by remember { mutableStateOf(false) }
var child2Checked by remember { mutableStateOf(false) }

TriCheckbox(
    CheckedState.from(child1Checked, child2Checked), // <<< From booleans
    onCheckedChange = {
        val checked = it.toBoolean()  // <<< To boolean
        child1Checked = checked
        child2Checked = checked
    },
) { Text("Parent") }
Column(Modifier.margin(left = 1.cssRem)) {
    Checkbox(child1Checked, onCheckedChange = { child1Checked = it }) { Text("Child 1") }
    Checkbox(child2Checked, onCheckedChange = { child2Checked = it }) { Text("Child 2") }
}

Label

Setting up HTML labels by hand can be pretty tedious -- you have to make sure the element you are targeting has a unique ID which you then specify on the label. The Label composable provided by Compose HTML works this way.

With Silk, we now provide our own convenience Label composable. We use Silk's ElementTarget class to make it a lot easier and more intuitive to use:

Row {
   Switch(...)
   Label(ElementTarget.PreviousSibling, "Dark Mode")
}

Row {
   Switch(...)
   Label(ElementTarget.PreviousSibling, "High Contrast")
}

The code above will automatically create temporary IDs behind the scenes to ensure the labels and the switches are correctly connected.

Thanks!

Finally, thanks to first-time contributor @tungbq who helped us clean up a bunch of comments, migrating them to use the more appropriate @see documentation attribute.

There are all manner of issues left before we hit 1.0, and we appreciate anyone who offers help no matter how big or small -- it all moves the needle forward!


Full Changelog: v0.13.11...v0.13.12

Don't miss a new kobweb release

NewReleases is sending notifications on new releases.