Check mark
A stroke check that draws itself, down the short leg and up the long one.
Check mark is a check you watch arrive. It is Phosphor's Check geometry at bold weight,
redrawn as one stroke so it can draw: the pen runs down the short leg to the vertex, then up
the long leg to the top. checked drives it, so the same mark draws when a step finishes and
clears when it is undone. Stepper swaps each finished
step's number for one.
Usage
import { CheckMark } from '@/components/ui/check-mark';
<CheckMark checked={done} className="text-primary" />The stroke is currentColor, so color it with a text class, and the size defaults to 1em
so it sits in a line of text at the text's size. Pass size for a fixed one, as a number of
pixels or any CSS length. The mark is a display-only icon, and it needs the motion package,
which the install adds.
Motion
| Rule | What happens |
|---|---|
| Draw | pathLength 0 to 1 in --duration-base on --ease-out, so the short leg lands quickly and the long leg settles. |
| Delay | delay (seconds) holds the draw, to sync with a parent's motion. Stepper passes the worm's 80ms trail delay. |
| Clear | Instant. Undoing is not an event worth animating. |
| Mount | Renders at its current state, no play-in. |
| Reduced motion | Appears and clears without drawing. |
While the delay runs the stroke stays hidden, then it draws. Toggle the three marks below to see them land one after another.
Props
Check mark takes these props, and the rest of an <svg>'s go on the <svg>, which ref
reaches.
| Prop | Type | Default | What it does |
|---|---|---|---|
checked | boolean | true | Draws the check when true and clears it when false. |
delay | number | 0 | Seconds to wait before the draw starts. A clear is never delayed. |
size | number | string | "1em" | The width and height, as pixels or any CSS length. |
className | string | Added to the <svg>. Set a text color here. |
Accessibility
- The mark is
aria-hidden, so a screen reader skips it. It decorates a state that its parent already names, like a step reading "completed" or a checkbox's own role, so give the state a text or an accessible name next to it. Given anaria-label, it isrole="img"with that name instead. - It is not focusable and takes no input.
- Color comes from
currentColor, so it follows the text color, including the system colors in forced colors. The mark never carries the state alone when a text name sits beside it. - Under reduced motion it appears and clears without drawing. Otherwise the draw is 200ms,
and it plays when
checkedturns true after mount.
When to use something else
- Checkbox when a person can toggle the state. It is a real control with a role, a name, keyboard handling, and its own check that scales in, while Check mark only shows a state someone else set.
- A plain Phosphor
Checkicon when the mark should not animate, like a bullet in a list. - Stepper for a row of steps. It uses Check mark for you.
Install
shadcn add @gesso/check-mark