Checkbox
A binary selection control. Supports uncontrolled and controlled usage, three sizes, and an indeterminate state for hierarchical selection.
Preview
Delivered every Monday morning.
This field must be checked.
Sizes
| Size | Dimensions | Border radius |
|---|---|---|
| sm | 14 × 14px | 4px |
| md | 16 × 16px | 5px |
| lg | 20 × 20px | 6px |
Indeterminate
Use indeterminate on a parent checkbox to indicate a partial selection within a group.
Implementation
Checkbox.tsx
tsx
import { Checkbox } from "@/components/ui/Checkbox";
import { useState, useRef } from "react";
// Uncontrolled
<Checkbox label="Accept terms" defaultChecked />
// Controlled
const [checked, setChecked] = useState(false);
<Checkbox
label="Subscribe to newsletter"
checked={checked}
onChange={(e) => setChecked(e.target.checked)}
/>
// Indeterminate (partial parent selection)
const allChecked = items.every((i) => i.checked);
const someChecked = items.some((i) => i.checked);
<Checkbox
label="Select all"
checked={allChecked}
indeterminate={someChecked && !allChecked}
onChange={(e) => setItems(items.map((i) => ({ ...i, checked: e.target.checked })))}
/>
// With helper text
<Checkbox
label="Enable notifications"
helperText="You can change this in settings at any time."
/>
// Error state
<Checkbox label="I agree to the terms" error="You must accept the terms to continue." />Props
All native <input type="checkbox"> attributes are forwarded (except size and type).
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | Visible label rendered to the right of the checkbox. |
helperText | string | — | Supplemental hint rendered below the label. |
error | string | — | Error message. Applies error styling to the checkbox. |
size | "sm" | "md" | "lg" | "md" | Controls the checkbox dimensions and label font size. |
indeterminate | boolean | false | Shows a minus icon indicating partial selection. Used for parent checkboxes in a group. |
ARIA roles
| Element | Role | Key attributes |
|---|---|---|
| Input | checkbox (implicit) | aria-checked (true/false/mixed), aria-describedby |
| Group | group (fieldset) | aria-labelledby (legend) |
Keyboard
| Key | Action |
|---|---|
| Space | Toggle the checked state |
| Tab | Move focus to the next focusable element |
| Shift+Tab | Move focus to the previous focusable element |
Accessibility
- →Built on a native <input type="checkbox"> — fully keyboard and screen-reader accessible.
- →The visual box is purely CSS; the real input is sr-only and receives focus.
- →Focus ring appears via focus-visible — keyboard-only, not shown on mouse click.
- →Indeterminate state is set via element.indeterminate = true, which assistive technology announces as 'mixed'.
- →Error text should be linked with aria-describedby pointing to the error message id.
- →In a checkbox group, wrap items in a <fieldset> with a <legend> to provide group context.