Checkbox

An accessible checkbox with checked, unchecked, and indeterminate states. Built on Radix UI.

Basic

With description

You can unsubscribe any time from the account settings.

Indeterminate (parent reflects partial selection)

Disabled

Installation

pnpm
pnpm dlx @hex-core/cli add checkbox

Controlled

Controlled checkbox

tsx
const [checked, setChecked] = useState(false);
<Checkbox checked={checked} onCheckedChange={setChecked} />

Indeterminate (parent/children)

Parent renders a dash when some (but not all) children are selected

tsx
const [items, setItems] = useState({ email: true, push: false });
const count = Object.values(items).filter(Boolean).length;
const parent = count === 0 ? false : count === 2 ? true : "indeterminate";

<Checkbox
  checked={parent}
  onCheckedChange={(v) => setItems({ email: v === true, push: v === true })}
/>

API Reference

PropTypeDefaultDescription
checked
booleanControlled checked state
defaultChecked
booleanDefault checked for uncontrolled
onCheckedChange
functionCallback: (checked: boolean | 'indeterminate') => void
disabled
booleanfalseDisable the checkbox
required
booleanfalseMark as required for form validation
className
stringAdditional CSS classes

AI Guidance

When to use

Use for boolean toggles in forms (agree to terms, enable options), multi-select lists, or parent/children trees where the parent reflects partial selection via the `indeterminate` state.

When not to use

Don't use for mutually exclusive options (use RadioGroup). Don't use for instant toggles (use Switch).

Common mistakes

  • Missing Label pairing
  • Using onChange instead of onCheckedChange
  • Forgetting that onCheckedChange can receive 'indeterminate' as well as boolean

Accessibility

Always pair with Label via htmlFor/id. Radix handles aria-checked automatically.

Related components

Token budget: 300