Tri-state Checkbox
A checkbox with a third state: checked, not checked, or some of both.
import com.pantrixui.components.elements.checkbox.PantrixTriStateCheckbox
- One target. The box, the label and the supporting text are one target: a press on the text changes the box too. However small the box is, the row takes as much room as the platform's touch target.
- Label and supporting text.
labelstands beside the box, andsupportingTextunder it in smaller text. The box is on the label's first line, however many lines the text runs to. - Three states.
PantrixTriStateCheckboxtakes aToggleableState: checked, unchecked or indeterminate. An indeterminate box draws a dash, and is read to a screen reader as indeterminate, not as unchecked. What a press leads to is the caller's to say. - Error.
errorturns the box and the supporting text to the theme'sdangerrole; a screen reader is told the input is invalid. - Form. The
PantrixCheckboxthat takes afieldgets its value, its error and its name from the form's field. The rule's message shows after the first change or on an attempt to submit the form, and takes the place of the supporting text. - Read-only and disabled. If
onCheckedChangeis null the box is read-only: it takes no press and no focus, and still says its name and its state.enabled = falsedraws the box in the disabled colours. - Colours of its own.
CheckboxColorstakes the fill, the tick and the edge separately; one that is left out stays in the theme's role. A disabled box and a box in error are drawn in the theme's colours even when colours are given. - Style.
CheckboxStylechanges the box's size, its corners and the thickness of its lines. The box is 18dp, and 22dp on iOS; its corners are the small step of the shape scale. - The box at the end.
controlPosition = ControlPosition.Endputs the box at the end of the label: given a width, the row has the box at its end. - Motion. The tick is drawn on and off, and the fill fades in and out with it. Where the theme's motion is reduced, both happen at once.
Examples
Three states: select all
PantrixTriStateCheckbox draws a third state. While some of the boxes under it are selected, "All notifications" is neither checked nor unchecked: it shows a dash, and that is how a screen reader reads it.
The caller works out the state, not the box: On if all are selected, Off if none is selected, Indeterminate in between. onClick only reports that it was pressed; here it selects them all, and when all are selected it clears them all.
val notifications = listOf("Shipping status", "Promotions", "Account security")
var chosen by remember { mutableStateOf(setOf(notifications.first())) }
val all = when (chosen.size) {
0 -> ToggleableState.Off
notifications.size -> ToggleableState.On
else -> ToggleableState.Indeterminate
}
Column(verticalArrangement = Arrangement.spacedBy(PantrixTheme.spacing.xs)) {
PantrixTriStateCheckbox(
state = all,
onClick = { chosen = if (all == ToggleableState.On) emptySet() else notifications.toSet() },
label = "All notifications",
tagKey = "all_notifications"
)
Column(modifier = Modifier.padding(start = PantrixTheme.spacing.xl)) {
notifications.forEachIndexed { index, name ->
PantrixCheckbox(
checked = name in chosen,
onCheckedChange = { on -> chosen = if (on) chosen + name else chosen - name },
label = name,
tagKey = "notification_$index"
)
}
}
}
API
state
A checkbox with a third state: checked, not checked, or some of both.
| Parameter | Type | Default | What it is |
|---|---|---|---|
state | ToggleableState | checked, not checked, or indeterminate. | |
onClick | (() -> Unit)? | called when the user presses the checkbox. Null makes it read-only. | |
modifier | Modifier | Modifier | the row's modifier. |
enabled | Boolean | true | whether the checkbox can be pressed. One that cannot is drawn in the disabled colours and says so. |
label | String? | null | the text beside the box: part of the target, and the checkbox's name for a screen reader. |
supportingText | String? | null | help under the label, in a smaller type: the message, while error is true. |
error | Boolean | false | whether the value is wrong: the box and the supporting text turn to the danger role, and a screen reader is told the input is invalid. |
style | CheckboxStyle? | null | this call's own style: over every enclosing one and under the density. Only the fields it sets change, on every platform. |
colors | CheckboxColors? | null | this checkbox's own colours: the ones it sets, with the theme's for the rest. A disabled box and one in error keep the theme's. |
contentDescription | String? | null | what a screen reader says for the checkbox where it has no label, or in place of it. |
tagKey | String? | null | the checkbox's automation key: the row is Checkbox_<tagKey>. |
interactionSource | MutableInteractionSource? | null | the checkbox's interactions, hoisted. It keeps a source of its own when this is null. |
controlPosition | ControlPosition | ControlPosition.Start | where the box stands: before the label, as a list of choices has it, or after it. After it, the box is at the end of the width the row is given, Modifier.fillMaxWidth() lining it up with the others, or right after the label where the row is given none; the label wraps in what the box leaves. |
CheckboxStyle
PantrixCheckbox's box: its size, its corners and its edge.
| Parameter | Type | Default | What it is |
|---|---|---|---|
size | Dp | Dp.Unspecified | The box's width and height, its edge included. |
shape | ShapeSpec | ShapeSpec.Unspecified | The box's corners: a step of the brand's shape scale, so a brand with square corners has square boxes. |
strokeWidth | Dp | Dp.Unspecified | How thick the box's edge is, and the tick's and the dash's line. |
CheckboxColors
What PantrixCheckbox is painted with, for a checkbox that does not take the theme's: a colour that is set is used, and one that is left out stays the theme's role. A product gives the colours it changes and no others:
| Parameter | Type | Default | What it is |
|---|---|---|---|
checked | Color | Color.Unspecified | The box's fill when it is checked or indeterminate. The theme's primary. |
checkmark | Color | Color.Unspecified | The tick and the dash on the fill: the colour that reads on checked. The primary role's onColor. |
border | Color | Color.Unspecified | The box's edge when it is not checked. The theme's borderStrong: an empty box is nothing but its edge. |
Accessibility
- Screen reader. One checkbox is read: its name is its label, and its state is said in the theme's language. A box without a label gets its name from
contentDescription.