Question Sequence
Chain multiple Socratic components into a single flow. Asks one question at a time with pagination, skip/next actions, keyboard navigation, and edit-mode back-nav that restores prior answers.
Preview
↑↓to navigateEnterto selectEscto skip
Usage
import {
SequenceShell,
useQuestionSequence,
} from "@/components/socratic-ui/question-sequence";
import { SingleSelect } from "@/components/socratic-ui/single-select";
import { MultiSelect } from "@/components/socratic-ui/multi-select";
function MySequence() {
const seq = useQuestionSequence({
ids: ["vibe", "tools"],
onComplete: (answers) => console.log(answers),
});
return (
<SequenceShell
controller={seq}
render={(currentId) => {
switch (currentId) {
case "vibe":
return (
<SingleSelect
question="What's your vibe right now?"
options={[{ title: "Building mode" }, { title: "Planning mode" }]}
{...seq.bind<string | null>("vibe", null)}
/>
);
case "tools":
return (
<MultiSelect
question="Which of these are you actively using?"
options={[{ title: "Claude Code" }, { title: "Todoist" }]}
{...seq.bind<string[]>("tools", [])}
/>
);
}
}}
/>
);
}
API Reference
| Prop | Type | Default |
|---|---|---|
idsrequiredOrdered list of question ids. Drives pagination and keys the transition between steps. | string[] | — |
defaultAnswersUncontrolled initial answers map, keyed by question id. | Record<string, unknown> | — |
answersControlled answers map. When provided, the hook becomes a pure dispatcher — the consumer owns state. | Record<string, unknown> | — |
onAnswerChangeFires whenever a question's answer changes, regardless of whether the hook is controlled. | (id: string, value: unknown) => void | — |
onCompleteFires when the user submits from the terminal question (⌘Enter or the primary button). | (answers: Record<string, unknown>) => void | — |
onCloseFires when the user closes the sequence via the × button or by pressing Esc on the terminal question. | () => void | — |