Checkbox
Multi-select choice with checked, indeterminate and invalid states, powered by Radix UI.
Preview
Live preview
Usage
Examples
Indeterminate parent row
const [state, setState] = useState<boolean | 'indeterminate'>('indeterminate')
<Checkbox
checked={state}
onCheckedChange={setState}
aria-label="Select all"
/>
<span>Select all</span>Label, sizes and invalid state
<div className="flex items-center gap-3">
<Checkbox size="sm" aria-label="Sm" />
<Checkbox size="md" aria-label="Md" />
<Checkbox size="lg" aria-label="Lg" />
<Checkbox invalid aria-label="Invalid" />
</div>Disabled row
<label className="flex items-center gap-3 opacity-50">
<Checkbox disabled aria-label="Disabled option" />
<span className="text-sm">Requires admin rights</span>
</label>Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| checked | "checked" | "indeterminate" | boolean | — | Controlled state. Use onCheckedChange to update it. |
| defaultChecked | boolean | — | Uncontrolled initial state. |
| onCheckedChange | (checked: boolean | "indeterminate") => void | — | Fires when the box toggles via click, Space key or pointer. |
| size | "sm" | "md" | "lg" | "md" | Box size — keeps the 44px hit target with a wrapping label. |
| invalid | boolean | — | Sets aria-invalid and the destructive border. |
| disabled | boolean | — | Native disabled state via Radix — dimmed and inert. |
| required / name / value | boolean / string / string | — | Forwarded to the hidden input so native forms keep working. |
Accessibility
Accessibility notes
- Wrap the checkbox in a <label>, or give it aria-label / an associated Label — the box alone has no accessible name.
- The label must be clickable: it doubles the hit target and is the primary way motor-impaired users toggle.
- indeterminate is announced as "partially checked"; set it when a parent row mixes checked children.
- Space toggles the focused checkbox — never block the Space key on the control itself.
- Pass name and value so the hidden input submits inside a native <form>.