ui · Primitive
Checkbox
@devalok/shilp-sutra/ui/checkboxView in Storybook Hand-curated previews ship in rolling waves. See it live in Storybook →
Reference
Props
checked: boolean | "indeterminate"
onCheckedChange: (checked: boolean | "indeterminate") => void
size: "sm" | "md" | "lg"
error: boolean (shows red border)
indeterminate: boolean (overrides checked, shows dash icon)
disabled: boolean
Defaults
size="md"
Example
<Checkbox checked={agreed} onCheckedChange={(v) => setAgreed(v === true)} />
{/* With label */}
<label htmlFor="terms" className="flex items-center gap-ds-02">
<Checkbox id="terms" checked={agreed} onCheckedChange={(v) => setAgreed(v === true)} />
I agree to the terms
</label>
Composability
- FormField integration: Unlike Input/Textarea, Checkbox does NOT auto-consume FormField state — the
errorprop must be set explicitly. (Form-library convention differs for checkboxes since they often don't share the same visual grouping.) - Labels: Checkbox doesn't carry its own label — pair it with
<Label htmlFor="x" />+<Checkbox id="x" />, or wrap both in a<label>element. Screen readers rely on that association. - Controlled vs uncontrolled: Pass
checked+onCheckedChangefor controlled,defaultCheckedfor uncontrolled. Don't mix.
Gotchas
- indeterminate overrides checked visually
- Checkbox does NOT auto-consume FormField error state — pass
errorexplicitly if using inside a FormField - WCAG 2.5.8 minimum target size met at md (24px); sm (20px) may fail if not paired with enough label hit area
Changes
v0.22.0
- Changed Check indicator animation from scale-bounce to path-draw (stroke draws progressively). Indeterminate dash also draws in.
- Fixed Uncontrolled checkbox never showed checkmark —
checkedfrom props wasundefined, soisActivewas alwaysfalse. Now tracks internal state. - Added Hover state on unchecked checkbox (subtle background highlight).
v0.18.0
- Changed Bouncy check indicator animation migrated to Framer Motion
- Fixed Icon sizing uses design tokens consistently
v0.1.0
- Added Initial release