Capítulo 16 de 51

Chapter 16: Checkbox

Core Idea

A two-part tri-state (checked/unchecked/indeterminate) control that renders a <span> by default (to support a wrapping <label>) but can render as a real <button> via nativeButton + render when using sibling labels instead — always backed by a hidden native input for form participation.

Key Concepts

  • Anatomy: RootIndicator (visual check mark, only meaningfully shown when checked/indeterminate; supports keepMounted for CSS-driven show/hide animation).
  • Labeling — wrapping label (simplest): <label><Checkbox.Root /> Accept terms</label>.
  • Labeling — sibling label + native button: default Root renders <span> to stay valid inside a <label>; for htmlFor/id sibling-label patterns, prefer nativeButton render={<button />} — or, to keep a native <button> inside a wrapping <label> without invalid HTML, use the render-callback form so the hidden input renders outside the label: render={(buttonProps) => <label><button {...buttonProps} /> text</label>}.
  • Form integration: wrap in <Field.Root name="..."> + <Field.Label> for the fully wired accessible/validated pattern (see ch009 Forms, ch023 Field) instead of a bare <label>.
  • Tri-state: checked/defaultChecked/onCheckedChange for boolean state; indeterminate prop for the third visual state (does not affect the underlying checked value — must be managed alongside it).
  • parent prop: associates a Checkbox with a Checkbox Group parent (see ch017) for automatic indeterminate/select-all behavior.
  • uncheckedValue: the form value submitted when unchecked (native checkboxes submit nothing when unchecked; this lets you submit an explicit value instead).

Reference Tables

PartNotable propsNotable data attributes
Rootchecked/defaultChecked/onCheckedChange, indeterminate, value/uncheckedValue, parent, nativeButton, name/form, disabled/readOnly/requireddata-checked, data-unchecked, data-indeterminate, data-disabled, data-readonly, data-required, data-valid/data-invalid, data-dirty, data-touched, data-filled, data-focused
IndicatorkeepMountedsame state attributes as Root, plus data-starting-style/data-ending-style

Key Takeaways

  1. Default (<span> + wrapping <label>) covers most cases — only switch to nativeButton render={<button />} when the design requires a sibling-label layout (htmlFor/id) rather than a wrapping label.
  2. indeterminate is purely visual/ARIA — you must still manage checked yourself (typically false while indeterminate) based on child-selection state; Checkbox doesn't infer it.
  3. Prefer <Field.Root name> + <Field.Label> over a bare <label> once the checkbox is inside a real form — it adds description/error association for free.

Connects To

  • ch017 (Checkbox Group): parent prop and indeterminate "select all" pattern.
  • ch009 (Forms) / ch023 (Field): the recommended accessible-labeling + validation path.
  • ch041 (Switch): the two-state (no indeterminate) sibling component, similar API shape.