A control that allows the user to toggle between checked and not checked.
By clicking this checkbox, you agree to the terms.
Installation
Install the packages
Add the shadcn/ui component
Animate it
The CLI finds your shadcn/ui components through components.json, swaps their primitive imports for Animate UI's and removes the CSS animation classes Motion replaces.
Usage
Import from Animate UI instead of react-aria-components: it re-exports all of React Aria, with the animated controls below. Everything else stays the same.
import { Checkbox } from '@animate-ui/react/primitives/react-aria';
export function Terms() {
return (
<Checkbox defaultSelected>
{({ isSelected }) => (
<>
<span data-slot="checkbox-indicator">
{isSelected && <CheckIcon />}
</span>
Accept terms and conditions
</>
)}
</Checkbox>
);
}React Aria lets you render the indicator yourself. Animate UI animates the content of the element marked data-slot="checkbox-indicator", which is what shadcn/ui renders: add the attribute to your own indicator.
Check animation
The check draws itself by default. With animation="pop" on the Checkbox, it pops in from half its size instead, and shrinks back out:
<Checkbox defaultSelected animation="pop">
{({ isSelected }) => (
<>
<span data-slot="checkbox-indicator">{isSelected && <CheckIcon />}</span>
Accept terms and conditions
</>
)}
</Checkbox>The same demo with checkAnimation="pop" (its Controls switch it back to draw):
By clicking this checkbox, you agree to the terms.
You can enable or disable notifications at any time.
To pop every check of your app at once (checkboxes, menus, selects, comboboxes), set checkAnimation="pop" on an AnimateUIProvider instead.
Animation
The motion of Animate UI v1's Radix UI checkbox (v1 had no React Aria one):
- Indicator: the check you render inside
data-slot="checkbox-indicator"draws itself when checking the box mounts it. Its stroke (pathLength) and its opacity go from 0 to 1 together in 0.3s, after a 0.2s delay, on Motion's default ease-out (v1's delay and curve, drawn a little slower than v1's 0.2s). When it unmounts, a copy of it erases in 0.3s in its place, then goes away: your render function stays the single source of truth, React Aria's state and render props are never delayed. Content that isn't an SVG shape fades the same way. - With
animation="pop"(orcheckAnimation="pop"on anAnimateUIProvider), the check pops instead: after the same 0.2s, it springs in from half its size out of a 2px blur (stiffness 500, damping 24, a little past its size), and shrinks back into its blur in 0.15s when the box is unchecked. Its stroke stays whole. The demo's Controls switch between the two. - Checkbox doesn't move: unlike v1's checkbox, it doesn't scale when pressed or hovered. The check (and, in the demo, the box's fill) answers the click.
- In the demo, the box's fill is a layer of its own (
before:in its classes) that grows from 70% while it fades in, in 300ms, and shrinks back as it fades out: the check draws over a box that is nearly full. The layer covers the box's border (before:-inset-px) and the border keeps its color, so no outline rings the growing fill. It's CSS, so copy the classes for the same effect; under reduced motion the layer only fades. - Checking with Space animates the same way: the state changes at once, the animation never delays it.
- A box that is already checked when it appears (on load, in a dialog that opens) renders at rest: only checking and unchecking animate it. On load, the check is your markup, rendered by the server before any script runs.
- Toggling again mid-animation turns back from where the check is.
isIndeterminateshows the indicator likeisSelected; an icon swapped for the indeterminate state draws without the delay, as v1's indeterminate line did. Inside aCheckboxGroup, each checkbox animates the same way.- Under reduced motion, the check only fades, drawn or popped (its stroke stays whole, nothing scales).
- The box's own colours are the component's CSS: shadcn/ui's
transition-colorsfades them. classNameandstylerender props keep working.
API Reference
Checkbox takes exactly the props of React Aria's Checkbox, plus the props below.
| Prop | Type | Default |
|---|---|---|
animation? | 'draw' | 'pop' | the closest AnimateUIProvider's checkAnimation, else 'draw' |
transition? | Transition | draw: { duration: 0.3, delay: 0.2, ease: [0, 0, 0.58, 1] }; pop: { type: 'spring', stiffness: 500, damping: 24, delay: 0.2 } |
exitTransition? | Transition | draw: { duration: 0.3, ease: [0, 0, 0.58, 1] }; pop: { duration: 0.15, ease: [0.23, 1, 0.32, 1] } |
AnimateUIProvider's tempo scales these transitions with everything else.