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 Base UI.
Installation
Complete project setup first. Your configuration
must select react/base and include your Design System ID.
pnpm exec frontfriend download questionnaire -f react --primitive base
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.
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>;
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>;
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.