Checkbox
Selects any number of options from a set, with an indeterminate state for partial selection.
Installation
npx shadcn@latest add https://qure-ui.qure.ai/r/checkbox.jsonUsage
import { Checkbox } from '@/components/ui/checkbox'<label className="flex items-center gap-2 text-sm">
<Checkbox defaultChecked onCheckedChange={setOn} /> Include prior studies
</label>A checkbox is for any number of choices from none upwards, and it takes effect when the surrounding form is submitted. If the change applies the instant it is made — a display setting, a notification preference — use a Switch, which says so by looking like a control rather than a form field. One choice from several is a Radio Group.
Wrap the box and its text in a <label>. The words are a far larger target than an 18px square,
and the association is what lets a screen reader announce the two together.
Sizes
16, 18 and 20px, with the tick scaled to match. md is the Figma box and the default. Use sm
in a dense table row where the checkbox sits on a single line of 12px text; lg where a finger
rather than a pointer is doing the work.
Every size keeps the same invisible hit area — the component draws after:-inset-x-3 after:-inset-y-2 around itself, so a small box is still comfortably clickable without the row
growing.
State
Unchecked, checked, indeterminate, disabled, and checked-and-disabled. A disabled checked box still shows its tick: a locked control has to keep reporting what it is locked to.
Select all
1 of 4 series selected.
The indeterminate state means "some of the children below are selected". The parent is indeterminate because of the children — it is a state you put the box into from code, never one a person can click their way back to. Click an indeterminate box and it becomes checked; click again and it clears.
<Checkbox
checked={selected.length === all.length}
indeterminate={selected.length > 0 && selected.length < all.length}
onCheckedChange={checked => setSelected(checked ? all : [])}
/>Base UI renders one indicator for both checked and indeterminate and tells you which through
state.indeterminate, which is why there is a single element here rather than a tick and a dash
that could disagree.
A "select all" that only selects the page in front of you, in a worklist that is paginated, is a well-known way to delete the wrong studies. Say which set it covers — "select all 12 on this page" — or make the count next to it do the saying.
With labels and descriptions
Pulls the two most recent studies of the same modality for comparison.
De-identified before it leaves the department.
Unavailable until the patient consent form is on file.
Field supplies the label association and the per-option description.
FieldItem lays the row out with a 16px gap and indents the description past the box, so it
lines up with the label rather than the control. disabled on the item greys the label and the
description alongside the box, which keeps the reason for the disabling readable.
A filter panel
Grouped checkboxes need a group name, and a <fieldset> with a <legend> is the cheapest way to
get one — otherwise "CT" and "Unread" arrive as six unattached options. Counts on the right tell
the reader what a filter will cost them before they apply it.
Contrast
The resting outline is --border-base-tertiary at 1px: 3.63:1 light, 4.17:1 dark. WCAG
2.2 SC 1.4.11 asks 3:1 of a UI component boundary, and an unchecked box is nothing but its
boundary.
The previous library hardcoded rgba(0,130,128,0.12) here — 12% teal, measuring 1.10:1,
in practice invisible against a white surface. If you change a control's border, measure it
rather than picking by eye.
Keyboard
Space toggles. Tab reaches each box individually — a set of checkboxes is not one tab stop the way a radio group is, because each is an independent decision. There is no arrow-key navigation and there should not be.
API Reference
Everything Base UI's Checkbox accepts, plus:
Prop
Type
The Base UI props worth knowing:
Prop
Type
parent also exists, for a select-all driven by Base UI's Checkbox Group rather than by your own
state. We do not ship a CheckboxGroup wrapper, so the parent/child logic here is the handful of
lines in the select-all example above.