Checkbox
StableA tick box with a visible label and hint. It can show a partly selected state.
Also known as check box, tick box
Install with npm install @tattva/ui (setup), or copy the code from the kit in Downloads.
Controlled checkbox
function Example() {
const [on, setOn] = useState(true);
return <Checkbox checked={on} onChange={setOn} label="Remember my choice" />;
}Your code keeps the checked value and updates it when the box changes.
When to use it
Lets a person tick or untick one option. It is for choices that take effect when a form is sent, and for picking several items at once.
Made of: Box · Check or dash · Label · Hint
Use it for
- A choice in a form, such as agreeing to terms.
- Picking several items from a list.
- A select-all box above a list, using the partly selected state.
Not for
- A setting that applies the moment it is flipped: use Switch.
- Exactly one choice from a few options: use RadioGroup.
- One choice from a long list: use Select.
Do and avoid
Do
- Write the label so it is true when the box is ticked, such as "Share this chat".
- Use the partly selected state only for a box that controls a list of other boxes.
- Keep the checked value in your own code and pass it back as checked.
- Say why a box is disabled in text nearby.
Avoid
- Do not use a Checkbox for a setting that applies at once. Use a Switch.
- Do not use one for a choice between exclusive options. Use a RadioGroup.
- Do not leave out both the label and ariaLabel.
- Do not show an error with the red border alone.
On a phone
- The whole row is the tap target and is at least 44px tall on touch screens, while the box stays 20px.
- The label and description wrap inside the row instead of running off the screen.
- Nothing depends on hover.
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| checkedrequired | boolean | none | Current state. The component is fully controlled. |
| onChangerequired | (checked: boolean) => void | none | Called with the new checked value when the box is pressed. |
| label | ReactNode | none | Visible label. Pressing it toggles the box, and it is the accessible name. |
| description | string | none | Visible hint under the label. Linked with aria-describedby. |
| indeterminate | boolean | none | Shows a dash instead of a check and sets aria-checked to mixed. Pressing the box still calls onChange. |
| invalid | boolean | none | Red border and aria-invalid. Show the error text yourself. |
| disabled | boolean | none | Dims the row, skips it in the tab order and blocks changes. |
| ariaLabel | string | none | Accessible name for when there is no visible label. |
| id | string | none | Id on the input. |
| className | string | none | Classes for the outer label row. |
| ...rest | InputHTMLAttributes<HTMLInputElement> | none | Other native input props, such as name or required, passed to the input. |
"Show code under the preview gives the code for the example on the stage."
In Figma
In Figma, one Checkbox switches all of this from its properties panel, across 20 variants. Each property sets the React prop beside it, so design and code use the same names.
| Figma property | React | Values |
|---|---|---|
| Checked | checked | On or off |
| Indeterminate | indeterminate | On or off |
| State | Hover, Pressed and Focus come from the browser. Disabled sets disabled. | Default, Hover, Pressed, Focus, Disabled |
| Label | label | Any text |
States
States this part has beyond its default look. Build each one your screen can reach. States set by a property are in the Code tab.
- hover
- The pointer shows a hand over the whole row, and the label is part of the click target.
- focus
- A visible focus ring appears around the box when you reach it with the keyboard.
- indeterminate
- Pass indeterminate to show a dash for a partly selected group. Pressing it calls onChange.
Tokens
Change one of these and every part that uses it follows.
--accent--fg-on-accent--border-strong--danger--surface--dur-fast--focus-ring
Built in
- It is a real checkbox, so the Tab key reaches it and Space flips it.
- The label is the name. The hint is read after it.
- The partly selected state is announced as mixed.
- On touch screens the row is at least 44px tall.
- In high-contrast mode the box and the checked state use system colors, so they stay visible.
- The focus ring comes from the global focus rule.
What you need to do
- Give it a visible label. If you cannot, pass ariaLabel so it still has a name.
- When it is invalid, show the error as text next to it. The red border is not enough on its own.
- In a group, wrap the boxes in a fieldset with a legend so the group has a name.
Built toward WCAG 2.2 AA and checked automatically; no independent audit yet. Read the accessibility guide