Summit
ComponentsSelection

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)
CheckboxSwitchRadio Group
PurposeAny number of options, each on or offOne setting, on or offOne option from a set
EffectWhen its form is savedImmediatelyWhen its form is saved
Mixed StateA dash, set by indeterminateNoneNone
KeysSpaceSpace or EnterThe arrow keys
Tab StopsOne for each CheckboxOneOne for the group
Rolecheckboxswitchradio, in a radiogroup

Anatomy

ElementUsage
TickChecked state only
BoxRequired
Label*Optional
DashIndeterminate state only
Focus outlineKeyboard 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.

DoStack Checkboxes 12px apart so that each keeps its hit area to itself.
Don’tWhen Checkboxes are stacked 4px apart, a click on the bottom edge of one box checks the next.

Content

StringRuleExampleCounterexample
LabelSentence case“Send me a copy”“Send Me a Copy”
LabelSay what happens when the box is checked“Attach a PDF copy”“Do not attach a PDF copy”
aria-labelName 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.

A Checkbox needs a name so that screen readers can announce it, as WCAG 2.2 SC 4.1.2 Name, Role, Value requires. To provide one, place it in a Field with a 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/checkbox

Usage

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.

Select Every Row
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.

On this page