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/components/checkbox'
Basic
checked + onChange for controlled, defaultChecked for uncontrolled.
onChange 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 FormItem
Without label / description only the box renders, so it picks up the
enclosing FormItem's Label, Description and Message through the
Headless UI Field. invalid defaults to the item'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 | |
onChange | (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 | FormItem invalid | aria-invalid, data-invalid, destructive border and ring |
disabled | boolean | Field / FormItem 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 aFormItem'sDescription/Messageare joined intoaria-describedby.invalidsetsaria-invalid, paints the border--destructiveand turns the keyboard ring destructive. 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.
- FormItem, Label, Message: the field wiring.