Questionnaire

A multi-step questionnaire with single-choice, multiple-choice, freeform, and skippable questions.

1 of 3
What should the agent build next?

Choose a direction or describe another task.

Questionnaire owns the ordered items, active item, answer state, validation, progress, and navigation. The containing page, card, dialog, drawer, or Composer owns close and cancellation behavior, persistence, transport, and branching.

Installation

import { Questionnaire } from "@o/pipeline/experimental/components/chat/questionnaire";

Usage

<Questionnaire.Root items={items} onSubmit={handleSubmit}>
  <Questionnaire.Header>
    <Questionnaire.Progress />
    <Questionnaire.Pagination>
      <Questionnaire.PaginationPrevious />
      <Questionnaire.PaginationNext />
    </Questionnaire.Pagination>
  </Questionnaire.Header>
  {items.map((question) => (
    <Questionnaire.Item
      key={question.name}
      name={question.name}
      required={question.required}
    >
      <Questionnaire.ItemHeader>
        <Questionnaire.ItemTitle>{question.title}</Questionnaire.ItemTitle>
        <Questionnaire.ItemDescription>
          {question.description}
        </Questionnaire.ItemDescription>
      </Questionnaire.ItemHeader>
      <Questionnaire.ItemChoices>
        {question.choices.map((choice) => (
          <Questionnaire.ItemChoice key={choice.value} value={choice.value}>
            {choice.label}
          </Questionnaire.ItemChoice>
        ))}
        <Questionnaire.ItemInput aria-label="Another answer" />
      </Questionnaire.ItemChoices>
      <Questionnaire.ItemError />
    </Questionnaire.Item>
  ))}
  <Questionnaire.Footer>
    <Questionnaire.Actions>
      <Questionnaire.Previous />
      <Questionnaire.Skip />
      <Questionnaire.Next />
      <Questionnaire.Submit />
    </Questionnaire.Actions>
  </Questionnaire.Footer>
</Questionnaire.Root>

Composition

Questionnaire.Root
├── Questionnaire.Header
│   ├── Questionnaire.Progress
│   └── Questionnaire.Pagination
│       ├── Questionnaire.PaginationPrevious
│       └── Questionnaire.PaginationNext
├── Questionnaire.Item
│   ├── Questionnaire.ItemHeader
│   │   ├── Questionnaire.ItemTitle
│   │   └── Questionnaire.ItemDescription
│   ├── Questionnaire.ItemChoices
│   │   ├── Questionnaire.ItemChoice
│   │   └── Questionnaire.ItemInput
│   └── Questionnaire.ItemError
└── Questionnaire.Footer
    └── Questionnaire.Actions
        ├── Questionnaire.Action
        ├── Questionnaire.Previous
        ├── Questionnaire.Skip
        ├── Questionnaire.Next
        └── Questionnaire.Submit

Select to continue

Use controlled item state to advance after a single choice is selected. A multiple-choice question keeps an explicit Next button, and a filled freeform input continues on Enter.

1 of 4
What would you like to accomplish?

Selecting an answer continues to the next question.

Multiple Selection

Use multiple for an item that accepts more than one fixed answer.

What context should the agent inspect?

Select every source that may affect the implementation.

Freeform Answer

Compose Questionnaire.ItemInput with fixed choices when the user can provide another answer.

How should the agent approach this refactor?

Choose a strategy or write a more specific instruction.

Explicit Skip

Add Questionnaire.Skip when an optional item may be intentionally left unanswered.

1 of 3
What kind of change is this?

Choose the category that best describes the work.

Shortcuts

Assign a letter or number key to each answer with shortcuts. Figma ask flows use number badges.

What should the agent do next?

Use the displayed shortcut or navigate with the keyboard.

Controlled

Control the active item from host state, such as returning to an invalid step.

1 of 3

Current checkpoint: Change scope

What may the agent change?

The host stores the active checkpoint while Questionnaire navigates.

Resume

Restore a saved active item and default answers, then reset changes back to that saved state.

2 of 3
How should the migration be verified?

These checks were selected during the previous session.

Conditional Items

Disable items that do not apply to the user’s earlier answers.

1 of 2
Where should the agent run?

Cloud runs add an environment question to this flow.

Read item status to opt into disabled navigation and custom action styling.

1 of 2
What may the agent modify?

Next is intentionally disabled until an answer is selected.

Animated Items

Animate the active item while keeping progress and navigation stationary. This story uses Tailwind’s starting: variant and discrete transitions so an item animates as it is revealed.

1 of 3
What should the agent do?

Choose the task for this run.

Composer Ask

Demonstrate Questionnaire inside Composer via the dynamic-content swap pattern — no Composer.Questionnaire part yet. Editor.Root stays outside the composer so the normal view and ask footer share one live editor: drafts survive the swap, the footer’s freeform answer submits on Enter, and dismissing returns any unsubmitted draft to the normal editor. Progress and navigation sit above the card; single choices advance, while multiple choices use Next. The mounted TipTap Placeholder extension does not update from later Editor.Root prop changes, so this composition uses one static placeholder across questionnaire items for now.

Accessibility

Questionnaire.Item renders a fieldset, and Questionnaire.ItemTitle renders its legend. Descriptions and active errors are associated with the current item, and invalid items and answer controls expose aria-invalid.

Fixed choices preserve native radio and checkbox behavior. Progress is exposed as a named progressbar, navigation uses real buttons, and inactive items and actions are hidden and inert. Successful navigation focuses the newly active item; failed validation focuses an available answer control.

Always give Questionnaire.ItemInput an accessible name with a visible label, aria-label, or aria-labelledby. A placeholder is not a label. See the Questionnaire accessibility guide for labeling custom compositions and the complete keyboard behavior.

API Reference

The props, data attributes, and render states for every part are documented on the @shadcn/react Questionnaire page. Pipeline renames the headless parts with an Item prefix and adds Header, Pagination, Footer, ItemHeader, and Actions as styled-only layout parts, plus styled PaginationPrevious/PaginationNext/Action buttons. Nav buttons ship default labels (“Previous”/“Skip”/“Next”/“Submit”), pagination buttons ship caret icons with accessible labels, and Next/Submit default intent="success" — so <Questionnaire.Next /> is complete as written. Props and data attributes still come from @shadcn/react; navigation components also accept pipeline Button props such as intent, size, and variant.