Card Sort
Open in playgroundMulti-bucket triage. Pick a bucket to make it active, then tap items to drop them into it. Classic MoSCoW sorting for product-spec scoping.
Preview
Usage
import { CardSort } from "@/components/socratic-ui/card-sort";
const [value, setValue] = useState<Record<string, string[]>>({});
<CardSort
question="Sort these features for v1"
buckets={[
{ id: "must", title: "Must have", tone: "affirm" },
{ id: "nice", title: "Nice to have" },
{ id: "not", title: "Not needed", tone: "muted" },
]}
items={[
{ title: "Auth system" },
{ title: "Analytics" },
{ title: "Dark mode" },
]}
value={value}
onChange={setValue}
/>
API Reference
| Prop | Type | Default |
|---|---|---|
questionrequiredThe headline shown above the bucket row. | string | — |
subtitleOptional supporting copy beneath the question. | string | — |
bucketsrequiredThe sorting categories. `tone` drives the bucket colour — `affirm` for must-have, `muted` for out-of-scope, `neutral` otherwise. | { id: string; title: string; subtitle?: string; tone?: 'affirm' | 'neutral' | 'muted' }[] | — |
itemsrequiredThe list of items users sort into buckets. | { title: string; subtitle?: string }[] | — |
valuerequiredMap of bucket id to the titles of items placed in that bucket. | Record<string, string[]> | — |
onChangerequiredCalled whenever the user places or removes an item. | (value: Record<string, string[]>) => void | — |
numberOptional leading question number, e.g. "06". | string | — |
motionOpt-in entrance animation config. Omit for static rendering; pass `{ enabled: true }` (or a preset from `motion.ts`) to animate in on mount. | SocraticMotion | — |