Checkbox
Supports an indeterminate state in addition to true/false.
Anatomy
import { Checkbox } from "@spacing-ui/core";
<Checkbox defaultChecked="indeterminate" onCheckedChange={(c) => console.log(c)}>
Accept terms
</Checkbox>;API
| Prop | Type | Default | Description |
|---|---|---|---|
checked / defaultChecked | boolean | "indeterminate" | false | |
onCheckedChange | (checked: boolean | "indeterminate") => void | — | |
disabled | boolean | false |
Accessibility
role="checkbox",aria-checked="true","false", or"mixed"- Space toggles (clicking
indeterminateadvances totrue)
Examples
Controlled with form state
const [accepted, setAccepted] = useState(false);
<form onSubmit={(e) => { e.preventDefault(); submit(accepted); }}>
<Checkbox checked={accepted} onCheckedChange={(v) => setAccepted(v === true)}>
I accept the terms
</Checkbox>
<button type="submit" disabled={!accepted}>Continue</button>
</form>Native form submission
Pass a name and the checkbox will participate in native form data:
<form action="/subscribe" method="post">
<Checkbox name="marketing" defaultChecked>Receive updates</Checkbox>
<button type="submit">Subscribe</button>
</form>The indeterminate state submits as unchecked.
Live demo
Indeterminate → checked → unchecked
Space (or click) on an indeterminate checkbox advances to true, matching the browser’s native tri-state cycle. From true, Space toggles to false.
Testing
const box = screen.getByRole("checkbox", { name: /accept/i });
expect(box).toHaveAttribute("aria-checked", "mixed");
await userEvent.click(box);
expect(box).toHaveAttribute("aria-checked", "true");Last updated on