Checkbox
A native checkbox with an 18px box, for independent yes/no choices and for picking several items from a list. It submits with forms like any <input type="checkbox">.
<Checkbox defaultChecked>Email me about product updates</Checkbox>Import
import { Checkbox } from "@merid/react";Examples
With description
description renders a second line under the label and links it with aria-describedby.
<Checkbox description="Includes invoices, receipts and plan changes.">
Billing notifications
</Checkbox>Controlled
Uncontrolled checkboxes use defaultChecked. To control one, pass checked and read event.target.checked in onChange.
const [checked, setChecked] = useState(false);
<Checkbox checked={checked} onChange={(e) => setChecked(e.target.checked)}>
I agree to the terms
</Checkbox>Indeterminate
indeterminate shows the mixed “–” state, typically on a parent that is partly selected. It sets the DOM indeterminate property, which assistive tech reports as aria-checked="mixed".
const all = selected.length === items.length;
const some = selected.length > 0 && !all;
<Checkbox checked={all} indeterminate={some} onChange={() => setSelected(all ? [] : items)}>
All teams
</Checkbox>Disabled and invalid
<Checkbox disabled>Disabled</Checkbox>
<Checkbox disabled defaultChecked>Disabled and checked</Checkbox>
<Checkbox invalid required>Accept the data processing agreement</Checkbox>Without a visible label
Omit children and pass aria-label, for example in a table's selection column.
<Checkbox aria-label="Select row" />API reference
The ref and native input attributes (checked, defaultChecked, onChange, name, value, …) go to the <input>. className and style go to the outer wrapper.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | – | Visible label next to the box. Omit and pass aria-label for a bare checkbox. Inside a `Field`, the Field label names the checkbox and children become its description. |
description | ReactNode | – | Secondary line under the label, linked via aria-describedby. |
indeterminate | boolean | false | Shows the mixed state and sets the DOM indeterminate property. |
invalid | boolean | – | Forces the invalid style (`data-invalid`) and `aria-invalid`. |
checked | boolean | – | Checked state (controlled). |
defaultChecked | boolean | – | Initial checked state (uncontrolled). |
disabled | boolean | – | Disables the input and dims the label. |
Styling
| Hook | Values |
|---|---|
.mrd-checkbox | Outer wrapper; receives className and style |
.mrd-checkbox__control | Box container |
.mrd-checkbox__input | The native <input> |
.mrd-checkbox__icon | Check / dash SVG |
.mrd-checkbox__text, __label, __description | Label column |
data-disabled, data-invalid | On the wrapper |
data-invalid | On the input when invalid; draws the danger ring |
data-indeterminate | On the input while mixed |
The invalid ring is driven by data-invalid on the input; aria-invalid carries the semantics. Checkbox has no component variables; it uses --mrd-accent, --mrd-line-strong and --mrd-danger.
Accessibility
- A native checkbox: checked state, disabled state and form submission come from the platform.
- The label is a real
<label htmlFor>, so clicking the text toggles the box. - Inside a
Field, the Field label names the checkbox (aria-labelledby). Children still render as a clickable label but are linked as its description (aria-describedby), so the control is never double-labelled. - Group related checkboxes in a
fieldsetwith alegend, or a container withrole="group"andaria-labelledby.
| Key | Action |
|---|---|
| Tab | Moves focus to the checkbox. |
| Space | Toggles the checkbox. |
Guidelines
Do
Write labels as positive statements that are true when checked: “Email me about updates”.
Avoid
Use negative labels like “Don’t send me emails” — checked-means-no is easy to misread.
Do
Use a checkbox for a choice that is saved when the form is submitted.
Avoid
Use it for a setting that takes effect immediately — that is a Switch.