Skip to content

Checkbox

Stable

Toggles a single option on or off, or selects any number of options from a set — committed when the form is submitted.

Anatomy

  1. 1BoxA 16px box with an invisible 24px hit area. Checked, it fills with the brand color and draws its check like a pen stroke; mixed, it shows a dash.
  2. 2DescriptionOptional detail about what the option does, in muted text.
  3. 3LabelNames the option. Clicking it toggles the box.

Installation

$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/checkbox.json

Usage

import { Checkbox } from "@/components/ui/checkbox"
import { Field, FieldLabel } from "@/components/ui/field"
<Field orientation="horizontal">
  <Checkbox id="terms" />
  <FieldLabel htmlFor="terms">Accept terms and conditions</FieldLabel>
</Field>

The check mark draws itself like a pen stroke when the box is checked. Checked and indeterminate boxes fill with the brand color — in prfct, color marks state and selection, while black is reserved for actions.

Examples

With a description

Put the label and a description in FieldContent next to the checkbox. The description explains consequences; the label stays short enough to scan.

Indeterminate

A parent checkbox that controls a group is indeterminate when only some children are checked. Set indeterminate alongside checked; choosing the parent then checks or clears every child. Indent the children so the hierarchy is visible, not just implied.

States

Disabled checkboxes fade to half opacity and ignore input. For errors, mark the checkbox aria-invalid, the field data-invalid, and explain what to do in a FieldError — the red border alone is not enough.

Choice cards

Wrap a whole field in FieldLabel to turn it into a selectable card: the entire card toggles the checkbox, and a checked card takes on a brand tint. Use cards for options that need a price, an image or a longer description.

Group

Related checkboxes belong in a FieldSet with a FieldLegend, so assistive technology announces the question — Email me when… — once, as people enter the group, instead of leaving each option without context. Give them the same name and distinct values to submit them as a list.

Email me when

Guidelines

When to use

  • For a single, independent opt-in: Remember me, Accept terms.
  • To select any number of options from a list, including none.
  • When the change takes effect only after the form is submitted.

When not to use

  • For settings that apply immediately — use a Switch.
  • For exactly one choice from a set — use a Radio Group.
  • For more than about ten options — use a multiple Combobox or Select.

Labels

Write labels as positive statements that describe the checked state. People should never have to decode a double negative to know what checking the box will do.

Send me product updates

Do.The checked state reads as a clear yes.

Don't stop sending me updates

Don’t.Negative labels make the unchecked state a double negative.

Layout

Stack checkboxes vertically, one per line, with the box on the left of its label. Vertical lists are faster to scan and keep every label aligned; horizontal rows work only for two or three very short options.

Accessibility

The visible control has role="checkbox" and aria-checked ("mixed" when indeterminate). Base UI renders a hidden native input for form submission and validation, applies the checkbox's id to it, and links a sibling <label htmlFor> to the visible control with aria-labelledby — so labels are both clickable and announced.

KeyBehavior
Tab
Moves focus to the checkbox. Focus shows a 2px ring offset from the box.
Space
Toggles the checkbox.
  • Always label. Use FieldLabel with htmlFor, wrap the checkbox in a label, or use aria-label only when a visible label is truly redundant (e.g. a row selector in a table with a clear column header).
  • Boundaries. The unchecked border uses the input token — 3:1 against the page for WCAG 1.4.11. Checked state is also conveyed by the check mark, not color alone.
  • Target size. The box is 16px, but an invisible hit area extends it to 24×24px (WCAG 2.2, 2.5.8) without affecting layout. Clicking the label toggles it too.
  • Groups. Use FieldSet and FieldLegend so the group's question is announced. For a parent/child hierarchy, the parent's aria-checked="mixed" tells screen reader users that only some children are selected.

API reference

Checkbox

Renders a <span role="checkbox"> and a hidden <input>. Accepts every prop of Base UI's Checkbox.Root.

PropTypeDefault
checked

Whether the checkbox is checked. Use with onCheckedChange when controlled.

booleanNo default
defaultChecked

The initial checked state when uncontrolled.

booleanfalse
onCheckedChange

Called when the checkbox is toggled.

(checked: boolean, details) => voidNo default
indeterminate

Shows a dash and sets aria-checked="mixed" — for parents of partially selected groups.

booleanfalse
name

Submits the checkbox with a form.

stringNo default
value

The submitted value when checked.

stringNo default
uncheckedValue

The submitted value when unchecked. By default nothing is submitted.

stringNo default
required

Requires the checkbox to be checked before submitting.

booleanfalse
disabled

Ignores input and fades the control.

booleanfalse
readOnly

Shows the state but prevents changing it.

booleanfalse
id

Applied to the hidden input, so a <label htmlFor> can target it.

stringNo default
aria-invalid

Shows the error state. Pair with data-invalid on the Field.

booleanNo default