---
title: Questionnaire
description: Collect ordered answers with progress, validation, and keyboard navigation.
icon: list-checks
author:
  name: shadcn
  url: https://github.com/shadcn
sidebar:
  badge: New
---

<PoweredBy packages={[
  { name: 'Shadcn UI', url: 'https://ui.shadcn.com/docs/components/base/questionnaire' },
]} />

<ComponentPreview name="questionnaire-demo" />

## Installation

```package-install
npx shadcn@latest add @redpanda/questionnaire
```

## Usage

Questionnaire manages an ordered set of questions, answer state, validation, progress, and navigation.

```tsx
import {
  Questionnaire,
  QuestionnaireActions,
  QuestionnaireChoice,
  QuestionnaireChoiceDescription,
  QuestionnaireChoices,
  QuestionnaireDescription,
  QuestionnaireError,
  QuestionnaireInput,
  QuestionnaireItem,
  QuestionnaireNext,
  QuestionnairePrevious,
  QuestionnaireProgress,
  QuestionnaireSkip,
  QuestionnaireSubmit,
  QuestionnaireTitle,
} from "@/components/redpanda-ui/questionnaire"
```

Define the ordered items on the root. Keep each rendered `QuestionnaireItem` name and selection mode aligned with its definition.

```tsx
const items = [
  {
    name: "direction",
    required: true,
    choices: [
      { value: "delegation" },
      { value: "questions" },
    ],
  },
] as const

<Questionnaire items={items} defaultItem="direction" onSubmit={handleSubmit}>
  <QuestionnaireProgress />
  <QuestionnaireItem name="direction" required>
    <QuestionnaireTitle>What should we prototype next?</QuestionnaireTitle>
    <QuestionnaireDescription>Choose one direction.</QuestionnaireDescription>
    <QuestionnaireChoices>
      <QuestionnaireChoice value="delegation">Sub-agent delegation</QuestionnaireChoice>
      <QuestionnaireChoice value="questions">Question prompts</QuestionnaireChoice>
      <QuestionnaireInput aria-label="Another direction" />
    </QuestionnaireChoices>
    <QuestionnaireError />
  </QuestionnaireItem>
  <QuestionnaireActions>
    <QuestionnairePrevious />
    <QuestionnaireSkip />
    <QuestionnaireNext />
    <QuestionnaireSubmit />
  </QuestionnaireActions>
</Questionnaire>
```

## Anatomy

```
Questionnaire
├── QuestionnaireProgress
├── QuestionnaireItem
│   ├── QuestionnaireTitle
│   ├── QuestionnaireDescription
│   ├── QuestionnaireChoices
│   │   ├── QuestionnaireChoice
│   │   │   └── QuestionnaireChoiceDescription
│   │   └── QuestionnaireInput
│   └── QuestionnaireError
└── QuestionnaireActions
    ├── QuestionnairePrevious
    ├── QuestionnaireSkip
    ├── QuestionnaireNext
    └── QuestionnaireSubmit
```

## Selection patterns

Use the default single-select mode for radio choices. Add `multiple` to both the item definition and `QuestionnaireItem` for checkbox choices.

```tsx
<QuestionnaireItem name="signals" multiple>
  <QuestionnaireTitle>What should every update include?</QuestionnaireTitle>
  <QuestionnaireChoices>
    <QuestionnaireChoice value="progress">Progress</QuestionnaireChoice>
    <QuestionnaireChoice value="decisions">Decisions</QuestionnaireChoice>
  </QuestionnaireChoices>
</QuestionnaireItem>
```

`QuestionnaireInput` provides a freeform answer within the active item. Always give it an accessible name using a visible label, `aria-label`, or `aria-labelledby`.

## Validation

Required items prevent navigation and submission until they have an answer. `QuestionnaireError` shows the active validation message and the answer controls expose `aria-invalid`.

Use the controlled `item`, `onItemChange`, and `invalid` props when validation or navigation is owned by application state.

## Keyboard behavior

- Set `shortcuts="letters"` or `shortcuts="numbers"` to select fixed choices with matching keys. Shortcuts are off by default.
- Up and down arrows move focus between answers.
- Left and right arrows move between answered questions.
- Enter advances from a selected choice. Control or Command + Enter advances from a freeform input.

## Accessibility

`QuestionnaireItem` renders a `fieldset`, while `QuestionnaireTitle` renders its `legend`. Descriptions and active errors are associated with the current item. Progress uses a named progress bar, and navigation uses real buttons. Inactive items and actions are hidden and inert.

## Credits

- Ported from the [Shadcn UI Questionnaire](https://ui.shadcn.com/docs/components/base/questionnaire).
