Skip to main content

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.

Loading example

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.

Loading example

Indeterminate

indeterminate shows the mixed state (aria-checked="mixed", data-indeterminate) for a parent whose children are partly selected.

Loading example

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.

Loading example

Props

CheckboxProps extends Headless UI CheckboxProps (minus as, children) with:

PropTypeDefaultDescription
checkedbooleanControlled state; use defaultChecked for uncontrolled
defaultCheckedbooleanfalse
onChange(checked: boolean) => void
indeterminatebooleanfalsearia-checked="mixed", data-indeterminate, a dash instead of a check
labelReactNodeVisible label; wraps the control in a Field so clicking it toggles
descriptionReactNodeHelper text wired through aria-describedby
labelPosition'end' | 'start''end'Where the label and description sit relative to the box
size'sm' | 'md' | 'lg''md'
invalidbooleanFormItem invalidaria-invalid, data-invalid, destructive border and ring
disabledbooleanField / FormItem disabledLeave unset to inherit; an explicit false overrides the context
namestringNative form participation via a hidden input
valuestring'on'Submitted value when checked
classNamestringMerged last onto the box (the element ref points at)

Slots

SlotElementNotes
[data-slot="checkbox"]spanThe box. Headless UI sets data-checked, data-indeterminate, data-hover, data-focus, data-disabled; ZUI adds data-invalid
[data-slot="checkbox-indicator"]svgCheck / dash glyph; aria-hidden, fades in when checked or indeterminate
[data-slot="checkbox-field"]divPresent with label / description: the Headless UI Field
[data-slot="checkbox-text"]divColumn 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" and aria-checked (true, false or mixed); a hidden input carries name / value to the form.
  • Space toggles the value; Tab moves through boxes in document order.
  • With label the <label> is associated to the box through the Field, so clicking the label toggles it. Pass the same id on the control when you set one; the label's htmlFor follows it.
  • description and a FormItem's Description / Message are joined into aria-describedby.
  • invalid sets aria-invalid, paints the border --destructive and turns the keyboard ring destructive. Keyboard focus shows the shared --ring ring (focus-visible only).
  • disabled sets data-disabled and aria-disabled on the box and dims the label.