Checkbox
A real checkbox whose fill grows from the centre and whose tick draws itself, with a mixed state that bends into the tick.
Used forSettings and consentTable row selectionTask and to-do listsSign-up terms
Install with the shadcn CLI
Templates
Need the whole page?
43 Next.js landing pages, each designed from scratch. Try any of them live; one is $39, all of them $99, and 5 are free.
Where it’s used
Settings and consent
Labelled options with a second line of description.
Table row selection
A header box that shows "some selected" as a dash.
Task and to-do lists
Ticks that draw as you finish things.
Sign-up terms
A required box inside a native form.
What it handles for you
Rebuilding a checkbox from divs means rebuilding forms, labels, Space and screen-reader state. This keeps the native input and only draws over it.
A tick that draws
pathLength stroke, 300ms after the fill lands; it retracts on uncheck.
Mixed state
checked="mixed" sets indeterminate on the input and grows a dash.
Native underneath
Forms, labels, Space and aria-checked behave as always.
Press feedback
The box gives under the finger and settles back.
Overview
Custom checkboxes often drop the native input and lose forms, labels and Space. This one keeps a real input underneath; on top, the box fills from its centre with a slight overshoot and the tick draws along its stroke, retracting the way it came. A mixed dash grows from the middle for "some selected".
States
- unchecked
- A hairline box; hover darkens the line.
- checked
- Primary fill grows from 0.4 with a slight overshoot (320ms) and the tick draws (300ms, 90ms later).
- mixed
- A dash grows from the centre (260ms).
- focus
- The ring and a 3px halo, from the keyboard only.
Usage
Props
| Prop | Type | Description |
|---|---|---|
| checked | boolean | "mixed" | Controlled state. |
| defaultChecked | booleandefault false | Initial state when uncontrolled. |
| onCheckedChange | (checked: boolean) => void | Called with the new state. |
| label / description | ReactNode | Text beside the box. |
| size | "sm" | "md"default "md" | 14px or 16px box. |
| ...input props | InputHTMLAttributes | name, value, required, disabled, ref. |
Accessibility and motion
- Reduced motion: the fill and tick change at once.
- The whole label is the hit area.
Requirements
React 19, Tailwind CSS v4 and shadcn/ui theme variables (any style, light and dark). Icons from lucide-react.
The CLI also installs ui-interaction-motion.
Source
Registry item: /r/checkbox.json


