Questionnaire

A multi-step survey — one question at a time, with progress, keyboard shortcuts, and navigation.

<Questionnaire
  shortcuts="letters"
  className="w-full max-w-md"
  onSubmit={(event) => {
    event.preventDefault()
  }}
>
  <QuestionnaireProgress />
  <QuestionnaireItem name="role" required>
    <QuestionnaireTitle>What best describes your role?</QuestionnaireTitle>
    <QuestionnaireDescription>
      This helps us tailor the onboarding.
    </QuestionnaireDescription>
    <QuestionnaireChoices>
      <QuestionnaireChoice value="designer">Designer</QuestionnaireChoice>
      <QuestionnaireChoice value="engineer">Engineer</QuestionnaireChoice>
      <QuestionnaireChoice value="founder">Founder</QuestionnaireChoice>
    </QuestionnaireChoices>
  </QuestionnaireItem>
  <QuestionnaireItem name="tools" multiple>
    <QuestionnaireTitle>Which tools do you use today?</QuestionnaireTitle>
    <QuestionnaireChoices>
      <QuestionnaireChoice value="figma">Figma</QuestionnaireChoice>
      <QuestionnaireChoice value="storybook">Storybook</QuestionnaireChoice>
      <QuestionnaireChoice value="tailwind">
        Tailwind CSS
      </QuestionnaireChoice>
    </QuestionnaireChoices>
  </QuestionnaireItem>
  <QuestionnaireActions>
    <QuestionnairePrevious />
    <QuestionnaireNext />
    <QuestionnaireSubmit />
  </QuestionnaireActions>
</Questionnaire>

Installation

npx shadcn@latest add @dotui/questionnaire

Usage

import {
  Questionnaire,
  QuestionnaireActions,
  QuestionnaireChoice,
  QuestionnaireChoices,
  QuestionnaireItem,
  QuestionnaireNext,
  QuestionnairePrevious,
  QuestionnaireSubmit,
  QuestionnaireTitle,
} from "@/ui/questionnaire"
<Questionnaire onSubmit={handleSubmit}>
  <QuestionnaireItem name="role" required>
    <QuestionnaireTitle>What best describes your role?</QuestionnaireTitle>
    <QuestionnaireChoices>
      <QuestionnaireChoice value="designer">Designer</QuestionnaireChoice>
      <QuestionnaireChoice value="engineer">Engineer</QuestionnaireChoice>
    </QuestionnaireChoices>
  </QuestionnaireItem>
  <QuestionnaireActions>
    <QuestionnairePrevious />
    <QuestionnaireNext />
    <QuestionnaireSubmit />
  </QuestionnaireActions>
</Questionnaire>

Anatomy

Questionnaire renders a form and shows one QuestionnaireItem at a time. An item is single-answer by default and multi-answer with multiple; its choices render as radios or checkboxes accordingly, with optional letter or number shortcuts. Free-text questions use QuestionnaireInput, and QuestionnaireError shows the active question's validation message.

The navigation renders itself: QuestionnairePrevious hides on the first question, QuestionnaireSkip only appears on optional questions, QuestionnaireNext advances, and QuestionnaireSubmit takes its place on the last question. QuestionnaireProgress reads "1 of 4"-style progress.

Examples

With Input

With Descriptions

API Reference

Questionnaire

A multi-step survey — one question at a time, with progress, keyboard shortcuts, and navigation. Renders a form.

PropType

QuestionnaireProgress

Where the reader is in the flow — "1 of 4"-style progress.

PropType

QuestionnaireItem

One question. Only the active item is shown.

PropType

QuestionnaireTitle

The question itself.

PropType

QuestionnaireDescription

Supporting copy under the title.

PropType

QuestionnaireChoices

The list of choices for a question.

PropType

QuestionnaireChoice

One selectable choice — radio for single-answer questions, checkbox when the item allows multiple. Shows its keyboard shortcut when the questionnaire enables them.

PropType

QuestionnaireChoiceDescription

Supporting copy under a choice's label.

Supports all span attributes.

PropType

QuestionnaireInput

A free-text answer field for the active question.

PropType

QuestionnaireError

The validation message for the active question.

PropType

QuestionnaireActions

The navigation row — previous, skip, and next or submit.

Supports all div attributes.

PropType

QuestionnairePrevious

Goes back one question. Hidden on the first.

PropType

QuestionnaireSkip

Skips the active question. Only rendered for optional questions.

PropType

QuestionnaireNext

Advances to the next question. Hidden on the last.

PropType

QuestionnaireSubmit

Submits the form. Only rendered on the last question.

PropType

Last updated on 8/31/2026