Checklist
FreeA list people tick through: a ticked item is struck out where it is, then settles into Done at the bottom, so what is left stays at the top. Add from the last row, reorder with Alt+arrows, undo from the line that confirms it.
pnpm dlx shadcn@latest add https://caliperui.site/r/checklist.jsonLaunch: multi-currency matching
1 of 4 doneWhen to use #
Use it for
- Launch, onboarding or review checklists people work through.
- Shared to-do lists inside a record.
Skip it when
- An agent's plan that people only watch; use the todo list.
- Tasks with owners and due dates; use a task table.
Decisions #
Why it is built this way, so you know what to keep when you change your copy.
Behaviour
- Strike first, then move
- A ticked item stays put, struck out, for a moment before it slides to Done. Moving it instantly would yank it from under the pointer and hide whether the tick landed.
- Every change can be taken back
- Ticks, removals and reorders each leave one line with Undo. There is no confirmation dialog for removing an item because undo is cheaper.
Styling
- Animate transform, never layout
- Rows slide with a transform from where they were to where they are, measured before and after the change, so the list never reflows twice.
Usage
- Respect reduced motion
- With reduced motion the rows move without sliding and the strike-through appears at once; the order and undo work the same.
Installation #
pnpm dlx shadcn@latest add https://caliperui.site/r/checklist.json
Adds its 3 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.
Usage #
This is the code behind the preview above.
import { useState } from "react" import { Checklist, type ChecklistItem } from "@/components/ui/checklist" export function ChecklistDemo() { const [items, setItems] = useState<ChecklistItem[]>([ { id: "a", text: "Write the release note", done: false }, { id: "b", text: "Record the two-minute walkthrough", done: false }, { id: "c", text: "Email workspaces with foreign-currency accounts", done: false }, { id: "d", text: "Update the help article on reconciliation", done: true }, ]); return ( <div className="w-full max-w-md"> <Checklist label="Launch: multi-currency matching" items={items} onItemsChange={setItems} /> </div> ); }
API reference #
Checklist
component
Accessibility #
It is built on native elements and keeps aria-keyshortcuts, aria-label, aria-hidden, aria-labelledby, aria-expanded and aria-controls in step with state. Changes that matter are announced through a live region.
Motion #
It checks prefers-reduced-motion itself and settles immediately instead of travelling. Every state is still reachable.