Checkbox
A checkbox is Headless UI's Checkbox (a <span role="checkbox"> with a
hidden input for form submission) drawn as an icon-sized box. With label
or description it wraps itself in a Headless UI Field, so clicking the
label toggles it and the description lands in aria-describedby.
import Checkbox from '@zuilib/primitives/checkbox'
Basic
checked + onCheckedChange for controlled, defaultChecked for
uncontrolled. onCheckedChange receives the boolean, not an event.
Sizes and label position
The box is size-4/5/6 (the shared icon scale, so it matches option
check marks and chevrons); the text beside it is text-sm for sm and
md, text-base for lg. labelPosition="start" puts the text first.
Indeterminate
indeterminate shows the mixed state (aria-checked="mixed",
data-indeterminate) for a parent whose children are partly selected.
In a Field
Without label / description only the box renders, so it picks up the
enclosing Field's Label, FieldDescription and FieldError.
invalid defaults to the field's invalid, and disabled (left
undefined) inherits from the Field / Fieldset.
Props
CheckboxProps extends Headless UI CheckboxProps (minus as,
children) with:
| Prop | Type | Default | Description |
|---|---|---|---|
checked | boolean | — | Controlled state; use defaultChecked for uncontrolled |
defaultChecked | boolean | false | |
onCheckedChange | (checked: boolean) => void | — | |
indeterminate | boolean | false | aria-checked="mixed", data-indeterminate, a dash instead of a check |
label | ReactNode | — | Visible label; wraps the control in a Field so clicking it toggles |
description | ReactNode | — | Helper text wired through aria-describedby |
labelPosition | 'end' | 'start' | 'end' | Where the label and description sit relative to the box |
size | 'sm' | 'md' | 'lg' | 'md' | |
invalid | boolean | Field invalid | aria-invalid, data-invalid, danger border and ring |
disabled | boolean | Field / Fieldset disabled | Leave unset to inherit; an explicit false overrides the context |
name | string | — | Native form participation via a hidden input |
value | string | 'on' | Submitted value when checked |
className | string | — | Merged last onto the box (the element ref points at) |
Slots
| Slot | Element | Notes |
|---|---|---|
[data-slot="checkbox"] | span | The box. Headless UI sets data-checked, data-indeterminate, data-hover, data-focus, data-disabled; ZUI adds data-invalid |
[data-slot="checkbox-indicator"] | svg | Check / dash glyph; aria-hidden, fades in when checked or indeterminate |
[data-slot="checkbox-field"] | div | Present with label / description: the Headless UI Field |
[data-slot="checkbox-text"] | div | Column holding label and description |
[data-slot="checkbox-label"] | label | — |
[data-slot="checkbox-description"] | p | — |
/* Consumer CSS: a circular checkbox for a brand that uses round toggles */
[data-slot="checkbox"] {
border-radius: var(--radius-full);
}
Accessibility
- The box has
role="checkbox"andaria-checked(true,falseormixed); a hidden input carriesname/valueto the form. - Space toggles the value; Tab moves through boxes in document order.
- With
labelthe<label>is associated to the box through the Field, so clicking the label toggles it. Pass the sameidon the control when you set one; the label'shtmlForfollows it. descriptionand aField'sFieldDescription/FieldErrorare joined intoaria-describedby.invalidsetsaria-invalid, paints the border--dangerand turns the keyboard ring the danger colour. Keyboard focus shows the shared--ringring (focus-visibleonly).disabledsetsdata-disabledandaria-disabledon the box and dims the label.
Related
- Switch: the same anatomy for an immediate on / off.
- Radio group: one of many.
- Field, Label, FieldError: the field wiring.