Meet Frontfriend.Your brand. Your rules. Your agents, connected.Explore what’s new
DocumentationQuestionnaire

Questionnaire

A native form that shows one question at a time. Compose Questionnaire with Progress, Item, Title, Description, Choices, Choice, ChoiceDescription, Input, Error, Actions, Previous, Skip, Next and Submit. Each part uses the Questionnaire prefix.

Interactive preview

Rendered from the shared Frontfriend stories with React Base, the same preview Studio shows. Styling comes from your Design System; the code below is native to Radix UI.

Installation

Complete project setup first. Your configuration must select react/radix and include your Design System ID.

pnpm exec frontfriend download questionnaire -f react --primitive radix

Review dependencies reported by the downloader and keep your source changes in version control.

Usage

import {
  Questionnaire,
  QuestionnaireItem,
  QuestionnaireTitle,
  QuestionnaireChoices,
  QuestionnaireChoice,
  QuestionnaireError,
  QuestionnaireActions,
  QuestionnaireSubmit,
} from "@/components/ui/questionnaire";
<Questionnaire onSubmit={(event) => event.preventDefault()}>
  <QuestionnaireItem name="useful" required>
    <QuestionnaireTitle>Was this answer useful?</QuestionnaireTitle>
    <QuestionnaireChoices>
      <QuestionnaireChoice value="yes">Yes, it helped</QuestionnaireChoice>
      <QuestionnaireChoice value="no">I need more detail</QuestionnaireChoice>
    </QuestionnaireChoices>
    <QuestionnaireError />
  </QuestionnaireItem>
  <QuestionnaireActions>
    <QuestionnaireSubmit />
  </QuestionnaireActions>
</Questionnaire>;

Answers and validation

Set name on each Item and value on each Choice. Item is a fieldset and Title is a legend. Choice uses a native radio or checkbox. required removes Skip. An optional question needs an answer or an explicit skip. multiple allows several choices and a freeform answer. In single mode, a fixed choice and a freeform answer exclude each other. Input accepts native input constraints; its Item supplies name and form. noValidate defaults to true. Set it to false to check native constraints on selected answers. Error text is linked to the item.

Progress and form data

Inactive items stay mounted, hidden and inert. Their answers remain in FormData. Use FormData.getAll() for repeated names. Native reset restores the initial item, default choices and default text. It also clears errors and skipped state. Supply items metadata for server rendering and the order of questions and shortcuts. Disabled items do not count toward progress. Check default selections after hydration when rendering on a server.

Keyboard

Up/Down moves among answers. Native radio keys also select. Left/Right changes questions outside radio and text inputs. Right never skips an unanswered item. Enter continues from a filled answer. Cmd/Ctrl+Enter validates, continues or submits. Letter and number shortcuts ignore text entry, IME, modified and repeated keys. Validation focuses the first invalid answer. Navigation focuses the next fieldset.

Examples

Default

import {
  Questionnaire,
  QuestionnaireProgress,
  QuestionnaireItem,
  QuestionnaireTitle,
  QuestionnaireChoices,
  QuestionnaireChoice,
  QuestionnaireError,
  QuestionnaireActions,
  QuestionnairePrevious,
  QuestionnaireSkip,
  QuestionnaireNext,
  QuestionnaireSubmit,
} from "@/components/ui/questionnaire";
<div
  className="text-neutral-strong"
  style={{
    width: "min(440px, calc(100vw - 32px))",
    display: "grid",
    gap: 16,
  }}
>
  <Questionnaire onSubmit={(event) => event.preventDefault()}>
    <QuestionnaireProgress />
    <QuestionnaireItem name="useful" required>
      <QuestionnaireTitle>Was this answer useful?</QuestionnaireTitle>
      <QuestionnaireChoices>
        <QuestionnaireChoice value="yes">Yes, it helped</QuestionnaireChoice>
        <QuestionnaireChoice value="no">I need more detail</QuestionnaireChoice>
      </QuestionnaireChoices>
      <QuestionnaireError />
    </QuestionnaireItem>
    <QuestionnaireActions>
      <QuestionnairePrevious />
      <QuestionnaireSkip />
      <QuestionnaireNext />
      <QuestionnaireSubmit />
    </QuestionnaireActions>
  </Questionnaire>
</div>;

Single

import {
  Questionnaire,
  QuestionnaireProgress,
  QuestionnaireItem,
  QuestionnaireTitle,
  QuestionnaireChoices,
  QuestionnaireChoice,
  QuestionnaireInput,
  QuestionnaireError,
  QuestionnaireActions,
  QuestionnairePrevious,
  QuestionnaireSkip,
  QuestionnaireNext,
  QuestionnaireSubmit,
} from "@/components/ui/questionnaire";
<div
  className="text-neutral-strong"
  style={{
    width: "min(440px, calc(100vw - 32px))",
    display: "grid",
    gap: 16,
  }}
>
  <Questionnaire onSubmit={(event) => event.preventDefault()}>
    <QuestionnaireProgress />
    <QuestionnaireItem name="team" required>
      <QuestionnaireTitle>Which team do you work with?</QuestionnaireTitle>
      <QuestionnaireChoices>
        <QuestionnaireChoice value="design">Design</QuestionnaireChoice>
        <QuestionnaireChoice value="engineering">
          Engineering
        </QuestionnaireChoice>
        <QuestionnaireChoice value="research">Research</QuestionnaireChoice>
      </QuestionnaireChoices>
      <QuestionnaireInput
        aria-label="Other team"
        placeholder="Enter another team"
      />
      <QuestionnaireError />
    </QuestionnaireItem>
    <QuestionnaireItem name="project" required>
      <QuestionnaireTitle>What is your project called?</QuestionnaireTitle>
      <QuestionnaireInput
        aria-label="Project name"
        placeholder="Project name"
      />
      <QuestionnaireError />
    </QuestionnaireItem>
    <QuestionnaireActions>
      <QuestionnairePrevious />
      <QuestionnaireSkip />
      <QuestionnaireNext />
      <QuestionnaireSubmit />
    </QuestionnaireActions>
  </Questionnaire>
</div>;

Multiple

import {
  Questionnaire,
  QuestionnaireProgress,
  QuestionnaireItem,
  QuestionnaireTitle,
  QuestionnaireDescription,
  QuestionnaireChoices,
  QuestionnaireChoice,
  QuestionnaireInput,
  QuestionnaireError,
  QuestionnaireActions,
  QuestionnairePrevious,
  QuestionnaireSkip,
  QuestionnaireNext,
  QuestionnaireSubmit,
} from "@/components/ui/questionnaire";
<div
  className="text-neutral-strong"
  style={{
    width: "min(440px, calc(100vw - 32px))",
    display: "grid",
    gap: 16,
  }}
>
  <Questionnaire onSubmit={(event) => event.preventDefault()}>
    <QuestionnaireProgress />
    <QuestionnaireItem name="updates" required multiple>
      <QuestionnaireTitle>Which updates do you want?</QuestionnaireTitle>
      <QuestionnaireDescription>
        Choose all that apply.
      </QuestionnaireDescription>
      <QuestionnaireChoices>
        <QuestionnaireChoice value="releases">
          Product releases
        </QuestionnaireChoice>
        <QuestionnaireChoice value="guides">
          Practical guides
        </QuestionnaireChoice>
        <QuestionnaireChoice value="events">Events</QuestionnaireChoice>
      </QuestionnaireChoices>
      <QuestionnaireInput
        aria-label="Other update"
        placeholder="Another topic"
      />
      <QuestionnaireError />
    </QuestionnaireItem>
    <QuestionnaireActions>
      <QuestionnairePrevious />
      <QuestionnaireSkip />
      <QuestionnaireNext />
      <QuestionnaireSubmit />
    </QuestionnaireActions>
  </Questionnaire>
</div>;

Freeform

import {
  Questionnaire,
  QuestionnaireProgress,
  QuestionnaireItem,
  QuestionnaireTitle,
  QuestionnaireInput,
  QuestionnaireError,
  QuestionnaireActions,
  QuestionnairePrevious,
  QuestionnaireSkip,
  QuestionnaireNext,
  QuestionnaireSubmit,
} from "@/components/ui/questionnaire";
<div
  className="text-neutral-strong"
  style={{
    width: "min(440px, calc(100vw - 32px))",
    display: "grid",
    gap: 16,
  }}
>
  <Questionnaire
    noValidate={false}
    onSubmit={(event) => event.preventDefault()}
  >
    <QuestionnaireProgress />
    <QuestionnaireItem name="project" required>
      <QuestionnaireTitle>What is your project called?</QuestionnaireTitle>
      <QuestionnaireInput
        aria-label="Project name"
        placeholder="Project name"
      />
      <QuestionnaireError />
    </QuestionnaireItem>
    <QuestionnaireItem name="website">
      <QuestionnaireTitle>Where can we find your project?</QuestionnaireTitle>
      <QuestionnaireInput
        type="url"
        aria-label="Website"
        placeholder="https://example.com"
      />
      <QuestionnaireError />
    </QuestionnaireItem>
    <QuestionnaireActions>
      <QuestionnairePrevious />
      <QuestionnaireSkip />
      <QuestionnaireNext />
      <QuestionnaireSubmit />
    </QuestionnaireActions>
  </Questionnaire>
</div>;

Optional Skip

import {
  Questionnaire,
  QuestionnaireProgress,
  QuestionnaireItem,
  QuestionnaireTitle,
  QuestionnaireDescription,
  QuestionnaireInput,
  QuestionnaireError,
  QuestionnaireChoices,
  QuestionnaireChoice,
  QuestionnaireActions,
  QuestionnairePrevious,
  QuestionnaireSkip,
  QuestionnaireNext,
  QuestionnaireSubmit,
} from "@/components/ui/questionnaire";
<div
  className="text-neutral-strong"
  style={{
    width: "min(440px, calc(100vw - 32px))",
    display: "grid",
    gap: 16,
  }}
>
  <Questionnaire onSubmit={(event) => event.preventDefault()}>
    <QuestionnaireProgress />
    <QuestionnaireItem name="referral">
      <QuestionnaireTitle>Who referred you?</QuestionnaireTitle>
      <QuestionnaireDescription>
        You can skip this question.
      </QuestionnaireDescription>
      <QuestionnaireInput aria-label="Referral" placeholder="Name or team" />
      <QuestionnaireError />
    </QuestionnaireItem>
    <QuestionnaireItem name="role" required>
      <QuestionnaireTitle>Which role fits you?</QuestionnaireTitle>
      <QuestionnaireChoices>
        <QuestionnaireChoice value="builder">Builder</QuestionnaireChoice>
        <QuestionnaireChoice value="reviewer">Reviewer</QuestionnaireChoice>
      </QuestionnaireChoices>
      <QuestionnaireError />
    </QuestionnaireItem>
    <QuestionnaireActions>
      <QuestionnairePrevious />
      <QuestionnaireSkip />
      <QuestionnaireNext />
      <QuestionnaireSubmit />
    </QuestionnaireActions>
  </Questionnaire>
</div>;

Required Error

import {
  Questionnaire,
  QuestionnaireProgress,
  QuestionnaireItem,
  QuestionnaireTitle,
  QuestionnaireDescription,
  QuestionnaireInput,
  QuestionnaireError,
  QuestionnaireActions,
  QuestionnairePrevious,
  QuestionnaireSkip,
  QuestionnaireNext,
  QuestionnaireSubmit,
} from "@/components/ui/questionnaire";
import * as React from "react";
export default function QuestionnaireExampleUsage() {
  const [invalid, setInvalid] = React.useState(true);
  return (
    <div
      className="text-neutral-strong"
      style={{
        width: "min(440px, calc(100vw - 32px))",
        display: "grid",
        gap: 16,
      }}
    >
      <Questionnaire
        noValidate={false}
        onSubmit={(event) => event.preventDefault()}
      >
        <QuestionnaireProgress />
        <QuestionnaireItem name="email" required invalid={invalid}>
          <QuestionnaireTitle>What is your work email?</QuestionnaireTitle>
          <QuestionnaireDescription>
            Enter a valid email address to continue.
          </QuestionnaireDescription>
          <QuestionnaireInput
            type="email"
            aria-label="Work email"
            placeholder="you@example.com"
            onChange={() => setInvalid(false)}
          />
          <QuestionnaireError />
        </QuestionnaireItem>
        <QuestionnaireActions>
          <QuestionnairePrevious />
          <QuestionnaireSkip />
          <QuestionnaireNext />
          <QuestionnaireSubmit />
        </QuestionnaireActions>
      </Questionnaire>
    </div>
  );
}

Controlled Progress

import {
  Questionnaire,
  QuestionnaireProgress,
  QuestionnaireItem,
  QuestionnaireTitle,
  QuestionnaireChoices,
  QuestionnaireChoice,
  QuestionnaireError,
  QuestionnaireInput,
  QuestionnaireActions,
  QuestionnairePrevious,
  QuestionnaireSkip,
  QuestionnaireNext,
  QuestionnaireSubmit,
} from "@/components/ui/questionnaire";
import * as React from "react";
export default function QuestionnaireExampleUsage() {
  const [item, setItem] = React.useState("team");
  return (
    <div
      className="text-neutral-strong"
      style={{
        width: "min(440px, calc(100vw - 32px))",
        display: "grid",
        gap: 16,
      }}
    >
      <Questionnaire
        item={item}
        onItemChange={setItem}
        onSubmit={(event) => event.preventDefault()}
      >
        <QuestionnaireProgress />
        <QuestionnaireItem name="team" required>
          <QuestionnaireTitle>Which team do you work with?</QuestionnaireTitle>
          <QuestionnaireChoices>
            <QuestionnaireChoice value="design">Design</QuestionnaireChoice>
            <QuestionnaireChoice value="engineering">
              Engineering
            </QuestionnaireChoice>
          </QuestionnaireChoices>
          <QuestionnaireError />
        </QuestionnaireItem>
        <QuestionnaireItem name="project" required>
          <QuestionnaireTitle>What is your project called?</QuestionnaireTitle>
          <QuestionnaireInput
            aria-label="Project name"
            placeholder="Project name"
          />
          <QuestionnaireError />
        </QuestionnaireItem>
        <QuestionnaireActions>
          <QuestionnairePrevious />
          <QuestionnaireSkip />
          <QuestionnaireNext />
          <QuestionnaireSubmit />
        </QuestionnaireActions>
      </Questionnaire>
      <output aria-label="Controlled item">Current item: {item}</output>
    </div>
  );
}

Letter Shortcuts

import {
  Questionnaire,
  QuestionnaireProgress,
  QuestionnaireItem,
  QuestionnaireTitle,
  QuestionnaireDescription,
  QuestionnaireChoices,
  QuestionnaireChoice,
  QuestionnaireInput,
  QuestionnaireError,
  QuestionnaireActions,
  QuestionnairePrevious,
  QuestionnaireSkip,
  QuestionnaireNext,
  QuestionnaireSubmit,
} from "@/components/ui/questionnaire";
<div
  className="text-neutral-strong"
  style={{
    width: "min(440px, calc(100vw - 32px))",
    display: "grid",
    gap: 16,
  }}
>
  <Questionnaire
    shortcuts="letters"
    onSubmit={(event) => event.preventDefault()}
  >
    <QuestionnaireProgress />
    <QuestionnaireItem name="priority" required>
      <QuestionnaireTitle>What should we improve first?</QuestionnaireTitle>
      <QuestionnaireDescription>
        Press A, B or C outside the text input.
      </QuestionnaireDescription>
      <QuestionnaireChoices>
        <QuestionnaireChoice value="speed">Speed</QuestionnaireChoice>
        <QuestionnaireChoice value="access">Accessibility</QuestionnaireChoice>
        <QuestionnaireChoice value="docs">Documentation</QuestionnaireChoice>
      </QuestionnaireChoices>
      <QuestionnaireInput
        aria-label="Other priority"
        placeholder="Another priority"
      />
      <QuestionnaireError />
    </QuestionnaireItem>
    <QuestionnaireActions>
      <QuestionnairePrevious />
      <QuestionnaireSkip />
      <QuestionnaireNext />
      <QuestionnaireSubmit />
    </QuestionnaireActions>
  </Questionnaire>
</div>;

Number Shortcuts

import {
  Questionnaire,
  QuestionnaireProgress,
  QuestionnaireItem,
  QuestionnaireTitle,
  QuestionnaireDescription,
  QuestionnaireChoices,
  QuestionnaireChoice,
  QuestionnaireError,
  QuestionnaireActions,
  QuestionnairePrevious,
  QuestionnaireSkip,
  QuestionnaireNext,
  QuestionnaireSubmit,
} from "@/components/ui/questionnaire";
<div
  className="text-neutral-strong"
  style={{
    width: "min(440px, calc(100vw - 32px))",
    display: "grid",
    gap: 16,
  }}
>
  <Questionnaire
    shortcuts="numbers"
    onSubmit={(event) => event.preventDefault()}
  >
    <QuestionnaireProgress />
    <QuestionnaireItem name="plan" required>
      <QuestionnaireTitle>Which plan fits your team?</QuestionnaireTitle>
      <QuestionnaireDescription>
        Press 1, 2 or 3 to select.
      </QuestionnaireDescription>
      <QuestionnaireChoices>
        <QuestionnaireChoice value="starter">Starter</QuestionnaireChoice>
        <QuestionnaireChoice value="team">Team</QuestionnaireChoice>
        <QuestionnaireChoice value="enterprise">Enterprise</QuestionnaireChoice>
      </QuestionnaireChoices>
      <QuestionnaireError />
    </QuestionnaireItem>
    <QuestionnaireActions>
      <QuestionnairePrevious />
      <QuestionnaireSkip />
      <QuestionnaireNext />
      <QuestionnaireSubmit />
    </QuestionnaireActions>
  </Questionnaire>
</div>;

Reset

import {
  Questionnaire,
  QuestionnaireProgress,
  QuestionnaireItem,
  QuestionnaireTitle,
  QuestionnaireChoices,
  QuestionnaireChoice,
  QuestionnaireError,
  QuestionnaireInput,
  QuestionnaireActions,
  QuestionnairePrevious,
  QuestionnaireSkip,
  QuestionnaireNext,
  QuestionnaireSubmit,
} from "@/components/ui/questionnaire";
import { Button } from "@/components/ui/button";
<div
  className="text-neutral-strong"
  style={{
    width: "min(440px, calc(100vw - 32px))",
    display: "grid",
    gap: 16,
  }}
>
  <Questionnaire
    defaultItem="team"
    onSubmit={(event) => event.preventDefault()}
  >
    <QuestionnaireProgress />
    <QuestionnaireItem name="team" required>
      <QuestionnaireTitle>Which team do you work with?</QuestionnaireTitle>
      <QuestionnaireChoices>
        <QuestionnaireChoice value="design" defaultChecked>
          Design
        </QuestionnaireChoice>
        <QuestionnaireChoice value="engineering">
          Engineering
        </QuestionnaireChoice>
      </QuestionnaireChoices>
      <QuestionnaireError />
    </QuestionnaireItem>
    <QuestionnaireItem name="project" required>
      <QuestionnaireTitle>What is your project called?</QuestionnaireTitle>
      <QuestionnaireInput aria-label="Project name" defaultValue="Atlas" />
      <QuestionnaireError />
    </QuestionnaireItem>
    <Button type="reset" variant="outline">
      Reset answers
    </Button>
    <QuestionnaireActions>
      <QuestionnairePrevious />
      <QuestionnaireSkip />
      <QuestionnaireNext />
      <QuestionnaireSubmit />
    </QuestionnaireActions>
  </Questionnaire>
</div>;

Form Data Submit

import {
  Questionnaire,
  QuestionnaireProgress,
  QuestionnaireItem,
  QuestionnaireTitle,
  QuestionnaireDescription,
  QuestionnaireChoices,
  QuestionnaireChoice,
  QuestionnaireInput,
  QuestionnaireError,
  QuestionnaireActions,
  QuestionnairePrevious,
  QuestionnaireSkip,
  QuestionnaireNext,
  QuestionnaireSubmit,
} from "@/components/ui/questionnaire";
import * as React from "react";
export default function QuestionnaireExampleUsage() {
  const [submitted, setSubmitted] = React.useState<
    [string, FormDataEntryValue][] | null
  >(null);
  return (
    <div
      className="text-neutral-strong"
      style={{
        width: "min(440px, calc(100vw - 32px))",
        display: "grid",
        gap: 16,
      }}
    >
      <Questionnaire
        onSubmit={(event) => {
          event.preventDefault();
          setSubmitted(Array.from(new FormData(event.currentTarget).entries()));
        }}
      >
        <QuestionnaireProgress />
        <QuestionnaireItem name="team" required multiple>
          <QuestionnaireTitle>
            Which teams will use the project?
          </QuestionnaireTitle>
          <QuestionnaireDescription>
            Choose one or more teams, or add another.
          </QuestionnaireDescription>
          <QuestionnaireChoices>
            <QuestionnaireChoice value="design">Design</QuestionnaireChoice>
            <QuestionnaireChoice value="engineering">
              Engineering
            </QuestionnaireChoice>
          </QuestionnaireChoices>
          <QuestionnaireInput
            aria-label="Other team"
            placeholder="Another team"
          />
          <QuestionnaireError />
        </QuestionnaireItem>
        <QuestionnaireItem name="project" required>
          <QuestionnaireTitle>What is your project called?</QuestionnaireTitle>
          <QuestionnaireInput
            aria-label="Project name"
            placeholder="Project name"
          />
          <QuestionnaireError />
        </QuestionnaireItem>
        <QuestionnaireActions>
          <QuestionnairePrevious />
          <QuestionnaireSkip />
          <QuestionnaireNext />
          <QuestionnaireSubmit />
        </QuestionnaireActions>
      </Questionnaire>
      {submitted && (
        <output aria-label="Submitted answers" role="status">
          Submitted answers
          <pre style={{ whiteSpace: "pre-wrap", overflowWrap: "anywhere" }}>
            {JSON.stringify(submitted, null, 2)}
          </pre>
        </output>
      )}
    </div>
  );
}

Disabled

import {
  Questionnaire,
  QuestionnaireProgress,
  QuestionnaireItem,
  QuestionnaireTitle,
  QuestionnaireChoices,
  QuestionnaireChoice,
  QuestionnaireError,
  QuestionnaireInput,
  QuestionnaireActions,
  QuestionnairePrevious,
  QuestionnaireSkip,
  QuestionnaireNext,
  QuestionnaireSubmit,
} from "@/components/ui/questionnaire";
<div
  className="text-neutral-strong"
  style={{
    width: "min(440px, calc(100vw - 32px))",
    display: "grid",
    gap: 16,
  }}
>
  <Questionnaire onSubmit={(event) => event.preventDefault()}>
    <QuestionnaireProgress />
    <QuestionnaireItem name="team" required>
      <QuestionnaireTitle>Which team do you work with?</QuestionnaireTitle>
      <QuestionnaireChoices>
        <QuestionnaireChoice value="design">Design</QuestionnaireChoice>
        <QuestionnaireChoice value="research" disabled>
          Research (unavailable)
        </QuestionnaireChoice>
      </QuestionnaireChoices>
      <QuestionnaireError />
    </QuestionnaireItem>
    <QuestionnaireItem name="internal" disabled>
      <QuestionnaireTitle>Internal review only</QuestionnaireTitle>
      <QuestionnaireInput aria-label="Internal note" />
      <QuestionnaireError />
    </QuestionnaireItem>
    <QuestionnaireItem name="project" required>
      <QuestionnaireTitle>What is your project called?</QuestionnaireTitle>
      <QuestionnaireInput
        aria-label="Project name"
        placeholder="Project name"
      />
      <QuestionnaireError />
    </QuestionnaireItem>
    <QuestionnaireActions>
      <QuestionnairePrevious />
      <QuestionnaireSkip />
      <QuestionnaireNext />
      <QuestionnaireSubmit />
    </QuestionnaireActions>
  </Questionnaire>
</div>;

API reference

Questionnaire API from @shadcn/react/questionnaire, with Frontfriend Button sizes and variants. Native HTML attributes remain available.

Questionnaire

Prop Type Default Description
className string — Additional classes on this part.
defaultItem string First enabled item Initial active item for uncontrolled progress. Reset restores this item.
item string — Controlled active item name. Accept the change event to move to another item.
items readonly QuestionnaireItemDefinition[] DOM order Metadata for server rendering and item order. Each entry has name, required?, disabled?, and choices?: { value, disabled? }[].
noValidate boolean true When false, validate native constraints on selected answers.
onItemChange (item: string) => void — Called when navigation requests another active item.
onReset React.FormEventHandler<HTMLFormElement> — Receives the native reset event. Reset restores initial answers and clears item status.
onSubmit React.FormEventHandler<HTMLFormElement> — Receives the native submit event after validation. Read answers with FormData.
shortcuts "letters" | "numbers" Off Choice shortcuts. Omit this prop to turn shortcuts off.

QuestionnaireActions

Prop Type Default Description
className string — Additional classes on this part.

QuestionnaireChoice

Prop Type Default Description
checked boolean — Controlled selected state. Accept the change event to update it.
className string — Additional classes on this part.
defaultChecked boolean false Initial selected state restored by reset.
disabled boolean false Disable this choice and exclude it from shortcuts.
onChange React.ChangeEventHandler<HTMLInputElement> — Receives the native input change event. Read event.target.checked for controlled choices.
render React.ReactElement | ((props, state) => React.ReactElement) Native label Custom element or render callback. State includes checked, disabled, invalid, shortcut and type.
value string — Value submitted under the item name when this choice is selected.

QuestionnaireChoiceDescription

Prop Type Default Description
className string — Additional classes on this part.

QuestionnaireChoices

Prop Type Default Description
className string — Additional classes on this part.
render React.ReactElement | ((props, state) => React.ReactElement) Native div Custom element or render callback. State includes shortcuts.

QuestionnaireDescription

Prop Type Default Description
className string — Additional classes on this part.
render React.ReactElement | ((props, state) => React.ReactElement) Native p Custom element or render callback. State includes native paragraph props.

QuestionnaireError

Prop Type Default Description
className string — Additional classes on this part.
render React.ReactElement | ((props, state) => React.ReactElement) Native p Custom element or render callback. State includes invalid.

QuestionnaireInput

Prop Type Default Description
className string — Additional classes on this part.
defaultValue string | number "" Initial text restored by reset.
disabled boolean false Disable this input and exclude its value from the answer.
onChange React.ChangeEventHandler<HTMLInputElement> — Receives the input change event. Read event.target.value for controlled input.
render React.ReactElement | ((props, state) => React.ReactElement) Native input Custom element or render callback. State includes disabled, filled and invalid.
type "date" | "datetime-local" | "email" | "month" | "number" | "password" | "search" | "tel" | "text" | "time" | "url" | "week" "text" Native text-entry input type. The item supplies name and form.
value string | number | readonly string[] — Controlled input value. Accept onChange to update it.

QuestionnaireItem

Prop Type Default Description
className string — Additional classes on this part.
disabled boolean false Exclude this item from progress, navigation, validation and submitted answers.
invalid boolean false Mark an external validation error.
multiple boolean false Use checkboxes and retain multiple fixed choices and freeform text.
name string — Unique item name. Also supplies the native form name for its answers.
onStatusChange (status: "unanswered" | "answered" | "skipped") => void — Called when the item status changes.
required boolean false Require an answer and hide Skip.

QuestionnaireNext

Prop Type Default Description
className string — Additional classes on this part.
disabled boolean false Disable this navigation button.
render React.ReactElement | ((props, state) => React.ReactElement) Native button Custom element or render callback. State includes disabled, shortcut, status and visible.
size React.ComponentProps<typeof Button>["size"] "default" Button size from the design system.
variant React.ComponentProps<typeof Button>["variant"] "default" Button appearance from the design system.

QuestionnairePrevious

Prop Type Default Description
className string — Additional classes on this part.
disabled boolean false Disable this navigation button.
render React.ReactElement | ((props, state) => React.ReactElement) Native button Custom element or render callback. State includes disabled, shortcut, status and visible.
size React.ComponentProps<typeof Button>["size"] "default" Button size from the design system.
variant React.ComponentProps<typeof Button>["variant"] "outline" Button appearance from the design system.

QuestionnaireProgress

Prop Type Default Description
className string — Additional classes on this part.
render React.ReactElement | ((props, state) => React.ReactElement) Native div Custom element or render callback. State includes current, total, first and last.

QuestionnaireSkip

Prop Type Default Description
className string — Additional classes on this part.
disabled boolean false Disable this navigation button.
render React.ReactElement | ((props, state) => React.ReactElement) Native button Custom element or render callback. State includes disabled, shortcut, status and visible.
size React.ComponentProps<typeof Button>["size"] "default" Button size from the design system.
variant React.ComponentProps<typeof Button>["variant"] "outline" Button appearance from the design system.

QuestionnaireSubmit

Prop Type Default Description
className string — Additional classes on this part.
disabled boolean false Disable this navigation button.
render React.ReactElement | ((props, state) => React.ReactElement) Native button Custom element or render callback. State includes disabled, shortcut, status and visible.
size React.ComponentProps<typeof Button>["size"] "default" Button size from the design system.
variant React.ComponentProps<typeof Button>["variant"] "default" Button appearance from the design system.

QuestionnaireTitle

Prop Type Default Description
className string — Additional classes on this part.
render React.ReactElement | ((props, state) => React.ReactElement) Native legend Custom element or render callback. State includes native legend props.

Configuration determines the actual classes and available styling hooks. See Theming & component configuration before introducing a repeated local override.