Questionnaire

A multi-step form for asking questions with single choice, multiple choice and free-form answers.

shadcn/ui docs
Question 1 of 3
Which framework do you use?

Pick the one you use most of the time.

Installation

pnpm dlx shadcn@latest add https://neobrutalism.dev/r/questionnaire.json

Usage

import {
  Questionnaire,
  QuestionnaireActions,
  QuestionnaireChoice,
  QuestionnaireChoices,
  QuestionnaireDescription,
  QuestionnaireError,
  QuestionnaireInput,
  QuestionnaireItem,
  QuestionnaireNext,
  QuestionnairePrevious,
  QuestionnaireProgress,
  QuestionnaireSkip,
  QuestionnaireSubmit,
  QuestionnaireTitle,
} from '@/components/ui/questionnaire'
const items = [
  { name: "plan", choices: [{ value: "free" }, { value: "pro" }], required: true },
  { name: "notes" },
] as const
 
<Questionnaire items={items} onSubmit={handleSubmit}>
  <QuestionnaireProgress />
  <QuestionnaireItem name="plan" required>
    <QuestionnaireTitle>Choose a plan</QuestionnaireTitle>
    <QuestionnaireChoices>
      <QuestionnaireChoice value="free">Free</QuestionnaireChoice>
      <QuestionnaireChoice value="pro">Pro</QuestionnaireChoice>
    </QuestionnaireChoices>
    <QuestionnaireError />
  </QuestionnaireItem>
  <QuestionnaireItem name="notes">
    <QuestionnaireTitle>Anything else?</QuestionnaireTitle>
    <QuestionnaireInput placeholder="Type your answer..." />
  </QuestionnaireItem>
  <QuestionnaireActions>
    <QuestionnairePrevious />
    <QuestionnaireSkip />
    <QuestionnaireNext />
    <QuestionnaireSubmit />
  </QuestionnaireActions>
</Questionnaire>

Questionnaire renders a form. The items prop declares the steps (name, optional choices and required) and drives the progress, navigation and validation. Read the answers from the form's FormData in onSubmit. Add multiple to a QuestionnaireItem to allow several choices, and shortcuts="letters" or shortcuts="numbers" to the root to enable keyboard shortcuts for the choices.

Examples

Default

Question 1 of 3
Which framework do you use?

Pick the one you use most of the time.

Validation

Free-text steps with QuestionnaireInput. Mark a step required, set the input type, and pass your own check to the invalid prop on QuestionnaireItem. QuestionnaireError shows its children as the message and blocks navigation until the answer is valid.

Question 1 of 2
What should we call you?

Controlled

Control the active step with the item and onItemChange props on Questionnaire and drive any UI from it, like a Progress bar.

Step 1 of 3
x
What best describes you?

Single Step

A single question with shortcuts="numbers", a preselected choice via defaultChecked and a disabled choice. Only QuestionnaireSubmit is needed since there is nothing to navigate.

Tabs or spaces?

Use the number keys to pick an answer, then press Enter.