Skip to content

Checkbox

Checkbox — one choice among any number, or a single agreement.

Beta · Forms · packages/css/src/components/checkbox.css

.pui-checkbox · __input (visually hidden) · __box · __label · :checked :indeterminate · --error · :disabled.

Checkbox — every size and every stateOpen in the workshop

Sizes across, states down.

  • Checked: false, true, indeterminate — a minus, for a parent whose children are mixed
  • Five states: default, hover, focus, error, disabled. Hover darkens the border, or the fill to action/primary/bg-hover when checked; focus is border/focus with the 3px ring at 15%; error is border/error — the whole box when checked
  • Label is a text property and can be hidden (Has label) when the row itself is the label — a table header, a card
  • The border is border/default and the label text/default

Use when the user can pick any number of options, or must confirm one thing — the privacy line on every site lead form.

Do not use when exactly one option must be chosen (Radio); the choice takes effect at once without a submit (Switch); the list is long (a multi-select Combobox).

Relates to Radio, Switch, Field (a checkbox row sits in a Field with its error), Label.

Anti-patterns a checkbox that submits on change · a label written as a question — labels state the thing · a checkbox and a switch in one form · an unlabelled box that leans on the text beside it.

Keywords: checkbox, check, tick, agree, consent, multi-select, indeterminate

Figma — page Checkbox, Radio & Switch: Checkbox (15 variants)

shadcn: checkbox

The class, the parts, and nothing that is not in the package. The same block opens checkbox.css.

<label class="pui-checkbox">
<input class="pui-checkbox__input pui-sr-only" type="checkbox">
<span class="pui-checkbox__box"></span>
<span class="pui-checkbox__label">I agree to the privacy policy</span></label>
What it is Note
State :hover · :focus-visible · :checked · :indeterminate · error = --error or [aria-invalid=“true”] on the input · :disabled (the row dims to .5) —

Every number here is measured on the rendered component: contrast (npm run contrast:render), the focus ring (npm run focus) and the keyboard (npm run keyboard). The floors are principle 12’s.

ink on ground reads floor the matrix calls it
#0b0202 on #ffffff 20.51 4.5 text.default on surface.page (promised) ok

1 distinct pair(s) rendered, 0 that axe calls a violation.

primitive on the indicator over the change
Checkbox surface/page shadow #6a66e4 2 px #ffffff 4.53 ok
Checkbox surface/card shadow #6a66e4 2 px #f2f2f7 4.06 ok
Checkbox surface/sunken shadow #6a66e4 2 px #f2f2f2 4.05 ok
Radio surface/page shadow #6a66e4 2 px #ffffff 4.53 ok
Radio surface/card shadow #6a66e4 2 px #f2f2f7 4.06 ok
Radio surface/sunken shadow #6a66e4 2 px #f2f2f2 4.05 ok

5 of 5 focus stop(s) in this block meet WCAG 2.4.13 on screen — the same crop screenshotted focused and unfocused, and the difference measured.

What the consumer’s script owes. nothing to write for Radio: native inputs sharing a name ARE a radio group and the browser gives the roving tabindex and the arrow keys. Checkbox takes Space, also the browser’s.

Tab order across the whole library is document order over 344 stops, and Shift+Tab is its exact reverse — no keyboard trap anywhere (WCAG 2.1.2).

Pepper UI v1.5.0

The Mobupps design system. 386 tokens, 88 components, 65 pages in the workshop — every page of this site generated from the repository, so nothing here is typed twice.