Shadcn Questionnaire
React questionnaire for onboarding, intake, and research flows. Built with TypeScript and Tailwind CSS for Next.js using Base UI — choices, freeform, skip, and progress.
A questionnaire is a multi-step form with one question on screen. Use it for onboarding, intake, or a research flow. Single choice, multiple, or a text field — then Next, Skip, or Submit.
Usage
import {
Questionnaire,
QuestionnaireActions,
QuestionnaireChoice,
QuestionnaireChoices,
QuestionnaireItem,
QuestionnaireNext,
QuestionnaireProgress,
QuestionnaireSubmit,
QuestionnaireTitle,
} from "@/components/ui/questionnaire"<Questionnaire items={items} onSubmit={handleSubmit}>
<QuestionnaireProgress />
{items.map(item => (
<QuestionnaireItem key={item.name} name={item.name} required={item.required}>
<QuestionnaireTitle>{item.title}</QuestionnaireTitle>
<QuestionnaireChoices>
{item.choices.map(choice => (
<QuestionnaireChoice key={choice.value} value={choice.value}>
{choice.label}
</QuestionnaireChoice>
))}
</QuestionnaireChoices>
</QuestionnaireItem>
))}
<QuestionnaireActions>
<QuestionnaireNext />
<QuestionnaireSubmit />
</QuestionnaireActions>
</Questionnaire>Pass the same items array to the root so progress, shortcuts, and skip know the list. onSubmit gets a form event — read FormData.
Composition
Multiple Selection
multiple on the item. FormData.getAll(name) returns every checked value.
Freeform Answer
QuestionnaireInput next to the choices. They type when none of the chips fit.
Explicit Skip
QuestionnaireSkip on an optional item. Required items hide Skip.
Shortcuts
shortcuts="letters" — A, B, C pick a choice. Arrow keys still move.
Custom Validation
QuestionnaireError under the choices. Block Next until the item is valid.
Controlled
Hold the current item id in state. Resume, deep-link, or drive it from a stepper.
Resume
Seed defaultItem from storage. They land on the last unanswered question.
Conditional Items
Drop or add items from the list based on a previous answer. The root re-reads items.
Navigation State
Disable Previous on the first item. Swap Next for Submit on the last.
Custom Progress
QuestionnaireProgress can render a fraction, a bar, or both.
Animated Items
Animate the incoming question. Keep the chrome still.
Card
Wrap the questionnaire in a Card when it is a section, not the page.
Dialog
Same flow inside a Dialog. Good for a mid-task prompt.
API
Prop
Type
QuestionnaireItem
Prop
Type
Keyboard
| Key | Action |
|---|---|
Tab | Move between choices and actions |
Space / Enter | Select the focused choice |
A–Z | Pick a choice when shortcuts="letters" |
Arrow keys | Move through choices |
Notes
One items array
Pass the same list to Questionnaire and to the map that renders items. Two copies drift — progress counts one list, the screen shows the other.
Read answers from FormData. Don't keep a parallel state object unless you are controlling the current item.
With other components
Label and error chrome
Radio GroupOne question, no steps
CheckboxA single multiple item
InputThe freeform slot
DialogMid-task prompt
ProgressA bar instead of 2 of 5
Questions
Related
Was this page helpful?
Sign in to leave feedback.
Progress
React progress for uploads, form steps, and long-running tasks. Built with TypeScript and Tailwind CSS for Next.js using Base UI — a track that fills as value moves.
Radio Group
React radio group for checkout, surveys, and settings. Built with TypeScript and Tailwind CSS for Next.js using Base UI — one option selected, arrow keys move.