Skip to content

Checkbox

Terminal window
$ npx shadcn@latest add https://lacodda.github.io/dowel/r/checkbox.json
See it liveUnchecked, checked, indeterminate and disabled, and a group with a parent box.→

The words are part of the component. A checkbox on its own is a nine-pixel target that says nothing; tied to its label it is the whole row, which is what a finger and a pointer both aim at. The commonest bug in a hand-rolled checkbox is a <label> sitting next to the input rather than tied to it — identical on screen, and it does nothing.

<Checkbox>Remember me</Checkbox>

Leave the words out only where the row already names it — a table cell — and then say so:

<Checkbox aria-label="Select row" />

The box is drawn rather than native. appearance: none on a real <input type="checkbox"> is the alternative, and it takes the indeterminate state with it: the dash is not something the input can be told to draw.

indeterminate is a state, not a third value. It means “some of the things below are checked”; clicking still means check-all. A tri-state value would make every caller handle a case that does not exist. It is announced as aria-checked="mixed", because a dash on its own is nothing to a screen reader.

CheckboxGroup exists for the parent box. Given allValues, it works out whether the parent is checked, unchecked or somewhere between, and clicking it sets all of them — the part that goes wrong when it is written by hand.

<CheckboxGroup allValues={['a', 'b']} defaultValue={['a']}>
<Checkbox parent aria-label="All" />
<Checkbox name="a" value="a">Apple</Checkbox>
<Checkbox name="b" value="b">Pear</Checkbox>
</CheckboxGroup>

Checkbox or Switch? If there is a Save button, it is a checkbox: an answer collected now and submitted later. If the change is the action, it is a switch.

Props

Read from the types in ui/checkbox.tsx, the file a product copies - so the description of each prop is also what an editor shows over it there.

Checkbox

PropTypeDefault
childrenReactNodeThe words next to the box. Omit only for a checkbox in a table cell, and then give aria-label instead.
checkedbooleanControlled state. Pair it with onCheckedChange.
defaultCheckedbooleanInitial state when the checkbox is uncontrolled.
onCheckedChange(checked: boolean) => voidCalled with the new state when the box is toggled.
indeterminatebooleanfalseSome but not all of what this stands for is checked. Draws a dash; clicking still checks everything.
parentbooleanThis is the box that stands for the whole group. Inside a CheckboxGroup with allValues, its state follows the children - checked, unchecked, or the dash in between - and clicking it sets all of them. Working that out by hand is where the indeterminate state usually goes wrong, so the group does it.
disabledbooleanStops the box taking input; the label dims with it.
requiredbooleanMarks the box as required for form validation.
namestringThe field name submitted with a form.
valuestringWhat this box contributes to the group's value array when checked, and what a form submits for it.
aria-labelstringThe accessible name, for a checkbox with no children.
classNamestring

CheckboxGroup

PropTypeDefault
childrenrequiredReactNode
valuestring[]The values of the checked boxes. Controlled; pair it with onValueChange.
defaultValuestring[]The values checked at first, when the group is uncontrolled.
onValueChange(value: string[]) => voidCalled with the new list of checked values.
allValuesstring[]Every value in the group, which is what makes a parent checkbox work.
disabledbooleanDisables every box in the group.
classNamestring

Accessibility

The examples on the stand, through axe 4.14.0 in a browser, in both themes, against WCAG 2.2 A and AA and axe's best practices: 18 rules applied and passed, and none failed. The accessibility report has every item.

Left to a person, where axe could not decide: aria-toggle-field-name.

History

Each release that changed ui/checkbox.tsx - the file a product copies - newest first.

  1. v0.41.0
    • docs read every props table from the component's types ee3b159
  2. v0.16.0
    • feat a field, and the three ways of choosing 7df746d