A native checkbox drawn by the theme, with an indeterminate (mixed) state.
Example
import { Checkbox, CheckboxGroup } from "@elements/ui/checkbox";
import { Label } from "@elements/ui/label";
<Label><Checkbox checked={form.terms} /> Accept terms and conditions</Label>
<Checkbox checked={rows.every((r) => r.on)}
indeterminate={rows.some((r) => r.on) && !rows.every((r) => r.on)}
onCheckedChange={(on) => rows.forEach((r) => r.on = on)}
attrs={{ "aria-label": "Select all" }} />
Parts
| Part |
What it is |
.checkbox |
The wrapper: the input and the indicator stacked in one cell. |
.checkbox-input |
The native <input type="checkbox">. |
.checkbox-indicator |
The check or the dash; ignores the pointer. |
.checkbox-group |
CheckboxGroup's role="group" column; name it with aria-labelledby in attrs. |
Attributes
Checkbox
| Attribute |
Type |
Default |
Description |
checked |
boolean (two-way) |
false |
Bind it to state; a click writes back. |
indeterminate |
boolean (two-way) |
false |
The mixed state. A click clears it and checks the box. |
value |
string |
"on" |
Submitted with name while checked. |
name |
string |
"" |
Form field name. |
uncheckedValue |
string | undefined |
undefined |
Submitted under name while unchecked. By default an unchecked box submits nothing. |
disabled |
boolean |
false |
Native disabled. |
readOnly |
boolean |
false |
Focusable and announced, but a click, Space or a label press does not change it. |
required |
boolean |
false |
The form will not submit until it is checked. |
invalid |
boolean |
false |
aria-invalid and the danger border. |
parent |
boolean |
false |
Inside a CheckboxGroup: checked when every child is, mixed when some are. A press checks all, then clears all, then brings back the last mix. |
class |
string |
"" |
Extra classes on the wrapper. |
attrs |
Record<string, string | number | boolean | undefined> |
{} |
Attributes for the <input>: id, aria-label, aria-describedby, data-*. |
onCheckedChange |
(checked: boolean, details: ChangeDetails) => void |
() => {} |
The user changed it, or a form reset restored it (not called for changes made in code). It runs before the change with details second (reason, event, cancel(), isCanceled); details.cancel() keeps the state. |
CheckboxGroup
| Attribute |
Type |
Default |
Description |
value |
string[] (two-way) |
[] |
The values of the checked boxes inside the group. Bind it to state; a press writes back. |
allValues |
string[] |
[] |
Every child value the parent box governs. Empty means every child in the group. |
disabled |
boolean |
false |
Disables every checkbox in the group. |
onValueChange |
(value: string[], details: ChangeDetails) => void |
() => {} |
The user changed the set, or a form reset restored it. details.cancel() keeps it. |
Keyboard
| Keys |
Action |
Space |
Toggles the checkbox. From the mixed state it becomes checked. |
Enter |
Does nothing: it neither toggles the box nor submits the form. |
Tab |
Moves to the next control. |
Data attributes
| Attribute |
Values |
On |
Description |
data-state |
"checked" | "unchecked" | "indeterminate" |
wrapper, input, indicator |
|
data-checked, data-unchecked, data-indeterminate |
present for the current state |
wrapper, input, indicator |
The same state as data-state, one attribute per value. |
data-disabled |
present while disabled |
wrapper, indicator |
|
data-invalid |
present while invalid |
input |
|
data-readonly |
present while readOnly |
wrapper, input, indicator |
|
data-required |
present while required |
wrapper, indicator |
|
data-parent |
present on a parent box |
input |
|
data-disabled |
present while the group is disabled |
CheckboxGroup |
|
Accessibility
- A native checkbox: its role, checked and mixed states are the browser's (the mixed state is announced from the indeterminate property).
- Name it with a wrapping
<Label>, <Label htmlFor>, aria-label in attrs, or a <Field>.
- A group of related checkboxes goes in an element with role="group" and aria-labelledby, or a
<FieldSet> with a legend.
- A CheckboxGroup parent box points aria-controls at its children.
- Focus shows the theme ring as a box-shadow; no state changes its size.
See also