Checkbox
A Checkbox allows users to turn one option on or off without changing the other options.
When to Use
- for an option that is saved with its form, such as “Send me a copy”
- as a stack of Checkboxes, to choose any number of options from a list, such as the events that send an email
- to select rows, in the first column of a Table, with one in the header to select all rows
When Not to Use
- to choose exactly one option from a set (use a Radio Group)
- for a setting that applies as soon as it changes (use a Switch)
- for a Button that stays pressed, like bold in a toolbar (use a Toggle)
| Checkbox | Switch | Radio Group | |
|---|---|---|---|
| Purpose | Any number of options, each on or off | One setting, on or off | One option from a set |
| Effect | When its form is saved | Immediately | When its form is saved |
| Mixed State | A dash, set by indeterminate | None | None |
| Keys | Space | Space or Enter | The arrow keys |
| Tab Stops | One for each Checkbox | One | One for the group |
| Role | checkbox | switch | radio, in a radiogroup |
Anatomy
| Element | Usage |
|---|---|
| Tick | Checked state only |
| Box | Required |
| Label* | Optional |
| Dash | Indeterminate state only |
| Focus outline | Keyboard focus only |
* A Checkbox with no visible label needs an aria-label.
Checkbox renders the box and its mark. For the label, use a Label or the FieldLabel of a Field, which can also contain a description and an error.
States
If a Checkbox represents a group and only some of the group is checked, set indeterminate. The Checkbox then shows a dash and reports aria-checked="mixed", whatever the value of checked. When users click it, onCheckedChange is called, but indeterminate doesn’t change, so clear it in the parent.
Behavior
When users click the box or its label, the Checkbox changes state.
Stack Checkboxes 12px apart with gap-3 so that the hit areas of two boxes don’t overlap and users don’t check the wrong box. See Sizing for the rule.
Content
| String | Rule | Example | Counterexample |
|---|---|---|---|
| Label | Sentence case | “Send me a copy” | “Send Me a Copy” |
| Label | Say what happens when the box is checked | “Attach a PDF copy” | “Do not attach a PDF copy” |
aria-label | Name the row when the Checkbox repeats in a Table | “Select INV-2026-014” | “Select” |
Accessibility
Base UI’s Checkbox renders a span with the role checkbox, and a hidden input next to it for the form.
FieldLabel, connect a Label to its id with htmlFor, or set aria-label. Use aria-label when there is no visible label, as in a Table row.Place a group of Checkboxes in a FieldSet with a FieldLegend so that the group has a name too. See Field for both parts.
Installation
npx shadcn@latest add @summit/checkboxUsage
import { Checkbox } from '@/components/ui/checkbox';
import { Label } from '@/components/ui/label';
<div className="flex items-center gap-2">
<Checkbox id="copy" />
<Label htmlFor="copy">Send me a copy</Label>
</div>;Select Every Row
To select all rows from a Table’s header, set checked when every row is selected and indeterminate when only some are.
const every = selected.length === invoices.length;
<Checkbox
aria-label="Select every invoice"
checked={every}
indeterminate={selected.length > 0 && !every}
onCheckedChange={(checked) => setSelected(checked ? invoices.map(({ number }) => number) : [])}
/>;API Reference
Checkbox adds no props. Its props are passed to the root of Base UI’s Checkbox. See the Base UI Checkbox documentation for checked, onCheckedChange, indeterminate, name, uncheckedValue, readOnly, and required.