Checklist
Row-style completion control. The whole row toggles a task done — line-through, muted color, and a subtle completion background.
Checklist is a completion control: a circular toggle + label wrapped in a native <label>, so the entire row is the click target. Checking a row strikes the label through, mutes its color, and tints the row background.
It is distinct from Checkbox — same shape, different meaning. Checkbox represents a selection (this option is chosen); Checklist represents a completion (this unit of work is done). Reach for Checklist in task lists, clinical procedures, and compliance checks.
Use it for
- Task / to-do lists where items get marked done
- Clinical procedure or compliance checklists
- Daily-maintenance runbooks with a running "n of N completed" counter
- Any discrete unit of work that is completed rather than selected
Import
import { Checklist } from '@brikdesigns/bds';Variants
Default
checked drives the completion styling; onCheckedChange fires with the next state when the row is clicked. Native Space / Enter toggle it — no manual key handling.
const [done, setDone] = useState(false);
<Checklist
label="Restock surgical gloves"
checked={done}
onCheckedChange={setDone}
/>Disabled
disabled locks the toggle and mutes the row — use during an async save or on read-only items.
<Checklist label="Verify autoclave log" checked disabled onCheckedChange={() => {}} />Pattern: checklist with a completion counter
The canonical use — a task sheet where the completion background makes done-vs-not glanceable and a counter tracks progress across rows.
const [items, setItems] = useState([
{ id: 'a', label: 'Refill hand sanitizer stations', checked: true },
{ id: 'b', label: 'Restock surgical gloves', checked: false },
{ id: 'c', label: 'Verify autoclave temperature log', checked: false },
]);
const toggle = (id) =>
setItems((prev) => prev.map((i) => (i.id === id ? { ...i, checked: !i.checked } : i)));
const completed = items.filter((i) => i.checked).length;
<>
<span>{completed} of {items.length} completed</span>
{items.map((item) => (
<Checklist
key={item.id}
label={item.label}
checked={item.checked}
onCheckedChange={() => toggle(item.id)}
/>
))}
</>When not to use
Don't use Checklist for form selection. If the box means "this option is selected" (filters, multi-select, opt-in), use Checkbox. Checklist's line-through + completion tint is wrong for a selection.
- Don't use it for a single on/off setting. A lone preference toggle is a Toggle Switch.
- Don't rebuild the row. The label is the click target by design — don't wrap it in another interactive element.
Accessibility
- Renders a native
<label>wrapping a real<input type="checkbox">, so the whole row is clickable andSpace/Entertoggle for free — no manualonKeyDown. - The circular toggle visual is
aria-hidden; the checkbox carries the state and thelabelprovides the accessible name. - Pass a text (or lightly marked-up)
label— it is the accessible name for the control.
API
| Prop | Type | Default |
|---|---|---|
label | ReactNode (required) | — |
checked | boolean (required) | — |
onCheckedChange | (checked: boolean) => void (required) | — |
disabled | boolean | false |
Plus all standard <label> HTML attributes (excluding onChange).
Related
- Checkbox — for selection, not completion
- Toggle Switch — single on/off setting
- Storybook playground
Progress circle
Circular indicator of completion. Use when a ring reads better than a bar — compact dashboards, completion meters, single-value tiles.
Completion toggle
The atomic circular control for a complete / not-complete state. The self-contained button primitive underneath Checklist — reach for it when the toggle stands alone.