Checkbox
A box for a yes/no choice, or for choosing several options. Primary and neutral, three sizes, checked, indeterminate, read-only, disabled and error.
Version 0.4.1 ·
Installation
bunx --bun shadcn@latest add @dga/checkboxInstalls Field too.
Usage
import { Checkbox } from "@/components/ui/checkbox";
import { Field, FieldContent, FieldLabel } from "@/components/ui/field";
export function ConsentField() {
return (
<Field orientation="horizontal" name="consent">
<Checkbox required />
<FieldContent>
<FieldLabel>I confirm the information is correct</FieldLabel>
</FieldContent>
</Field>
);
}Use a Checkbox when someone can choose none, one or several options, or confirm something before submitting. The choice is applied when the form is submitted; for a setting that takes effect at once use Switch. For exactly one of several options use Radio.
Anatomy
- Box (
<span role="checkbox">and a hidden<input>): the border and fill. - Mark: a check, or a dash when indeterminate.
- Label, helper text and error: from Field, beside the box.
Examples
States
Unchecked, checked, indeterminate, read-only, disabled, error and the neutral style.
Sizes
md is 24px (default), sm 20px and xs 16px. The label, not the box, is the click target, so it stays comfortable at every size.
Group with a parent
Set indeterminate on the parent when only some children are checked. The parent checks or clears them all.
RTL
The box is on the right (start) of its label and the helper text lines up under the label. The check mark is not directional, so it is not flipped.
Accessibility
| Key | Action |
|---|---|
| Tab | Moves focus to the checkbox. |
| Space | Checks or unchecks it. |
- The
checkboxrole witharia-checked(true,falseormixed), and a hidden native input for forms. - The label is from Field; clicking it toggles the box.
- The unchecked border is 3:1 or better on every surface; the checked fill and the mark are 3:1 against the surface and against each other (WCAG 1.4.11).
- Focus is a 2px outline 2px outside the box. Read-only keeps a 3:1 border.
- Errors show an icon and text with
aria-invalid, not a colour change alone.
API Reference
Checkbox
A box for a yes/no choice, or one of several. `indeterminate` shows a dash for a parent that is partly selected. Label it with a Field (`orientation="horizontal"`) or an enclosing label.
| Prop | Type | Default |
|---|---|---|
"xs" | "sm" | "md"Box size: `md` 24px, `sm` 20px, `xs` 16px. | "md" | |
| ||
"primary" | "neutral"`primary` (green) or `neutral` (black in light mode). | "primary" | |
| ||
booleanWhether the checkbox is in a mixed state: neither ticked, nor unticked. | No default | |
| ||
booleanWhether the checkbox is currently ticked. To render an uncontrolled checkbox, use the `defaultChecked` prop instead. | No default | |
| ||
booleanWhether the checkbox is initially ticked. To render a controlled checkbox, use the `checked` prop instead. | No default | |
| ||
booleanWhether the component should ignore user interaction. | No default | |
| ||
stringIdentifies the field when a form is submitted. | No default | |
| ||
(checked: boolean, details) => voidEvent handler called when the checkbox is ticked or unticked. | No default | |
| ||
booleanWhether the user should be unable to tick or untick the checkbox. | No default | |
| ||
booleanWhether the user must tick the checkbox before submitting a form. | No default | |
| ||
stringThe checkbox's value. Identifies it within a [Checkbox Group](https://base-ui.com/react/components/checkbox-group), falling back to `name` when omitted. When submitting a form, a checked box submits `value`; with no `value`, it submits the native "on". | No default | |
| ||
Also accepts every prop of the Base UI Checkbox (opens in a new tab).
Deviations from DGA
- In dark mode the checked fill stays green-600 on hover and press, because Figma's lighter greens give the white mark 1.4–2.1:1.
- The neutral check mark flips with the fill (new token
control-icon-neutral). - Read-only has a 3:1 border (Figma: 1.5:1).
| Change | Reason |
|---|---|
--control-primary-hovered (dark) and 1 more | Figma Dark lightens the checked fill on hover and press (green-300/400). The white check mark on it is 1.4–2.1:1. The fill stays green-600 and hover and press show on the ring and background instead. |
--control-icon-neutral (new) | The check mark on a neutral checkbox. The neutral fill is near-black in light mode and light grey in dark mode (control-neutral-checked), so the mark needs to flip too. Figma's control-icon-* tokens stay white (1.8:1 on the dark-mode fill). |
Checkbox, Radio: hover and pressed fill in dark mode | A white mark on the lighter fill is 1.4–2.1:1 (see the control-primary-hovered and -pressed fixes). |
Checkbox, Radio, Switch: read-only | The pale border is 1.5:1 on white. A read-only control keeps a 3:1 boundary. |
Contrast
108 pairs checked · all pass WCAG 2.1 AAShow 20 statesHide
| Variant / state | Light | Dark |
|---|---|---|
| unchecked border | 4.57:1 3:1 | 3.80:1 3:1 |
| unchecked border, hovered | 7.04:1 3:1 | 12.04:1 3:1 |
| border, error | 4.62:1 3:1 | 4.65:1 3:1 |
| border, read-only | 4.57:1 3:1 | 3.80:1 3:1 |
| focus ring | 17.31:1 3:1 | 17.49:1 3:1 |
| primary / checked (fill) | 4.54:1 3:1 | 3.68:1 3:1 |
| primary / checked (check mark) | 4.74:1 3:1 | 4.74:1 3:1 |
| primary / hovered (fill) | 8.18:1 3:1 | 3.68:1 3:1 |
| primary / hovered (check mark) | 8.55:1 3:1 | 4.74:1 3:1 |
| primary / pressed (fill) | 10.34:1 3:1 | 3.68:1 3:1 |
| primary / pressed (check mark) | 10.81:1 3:1 | 4.74:1 3:1 |
| neutral / checked (fill) | 17.93:1 3:1 | 9.38:1 3:1 |
| neutral / checked (check mark) | 18.74:1 3:1 | 10.07:1 3:1 |
| neutral / hovered (fill) | 7.04:1 3:1 | 12.04:1 3:1 |
| neutral / hovered (check mark) | 7.36:1 3:1 | 12.93:1 3:1 |
| neutral / pressed (fill) | 4.57:1 3:1 | 6.32:1 3:1 |
| neutral / pressed (check mark) | 4.77:1 3:1 | 6.79:1 3:1 |
| read-only mark | 4.77:1 3:1 | 9.38:1 3:1 |
| label | 14.53:1 AAA | 15.87:1 AAA |
| helper text | 4.77:1 AA | 6.32:1 AA |
Text needs 4.5:1, icons and focus rings 3:1. Disabled states are exempt. Full contrast report