- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Data Table
- Date Picker
- Dialog
- Direction
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input Group
- Input OTP
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Questionnaire
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toast
- Toggle
- Toggle Group
- Tooltip
- Typography
Questionnaire は、質問を 1 つずつ表示するためのスタイルなしフォーム プリミティブです。
回答、進捗、バリデーション、ナビゲーションを管理します。
エージェントへの確認プロンプト、オンボーディング、アンケート、受付フォーム、設定などに適しています。
スタイルなしパッケージでは、マークアップとスタイルを完全に制御できます。スタイル付きバージョンとテーマ付きの例については、 Questionnaire コンポーネントをご覧ください。
インストール#
pnpm add @shadcn/react
インポート#
import { Questionnaire } from "@shadcn/react/questionnaire"Questionnaire は 1 つの名前空間から各パーツをエクスポートします。各パーツは既定要素のネイティブ props を受け取ります。
構成#
<Questionnaire.Root>
<Questionnaire.Progress />
<Questionnaire.Item name="question">
<Questionnaire.Title />
<Questionnaire.Description />
<Questionnaire.Choices>
<Questionnaire.Choice>
<Questionnaire.ChoiceInput />
<Questionnaire.ChoiceLabel />
<Questionnaire.ChoiceShortcut />
</Questionnaire.Choice>
<Questionnaire.Input />
</Questionnaire.Choices>
<Questionnaire.Error />
</Questionnaire.Item>
<Questionnaire.Previous />
<Questionnaire.Skip />
<Questionnaire.Next />
<Questionnaire.Submit />
</Questionnaire.Root>Root はフォームを描画します。各 Item は fieldset で、Title がその legend になります。
ChoiceInput はネイティブのラジオボタンまたはチェックボックスを描画します。
スタイル付きバージョン#
スタイル付きレジストリ コンポーネントでは、フラットなコンポーネント名を使用します。
| Styled component | Unstyled part |
|---|---|
Questionnaire | Questionnaire.Root |
QuestionnaireProgress | Questionnaire.Progress |
QuestionnaireItem | Questionnaire.Item |
QuestionnaireTitle | Questionnaire.Title |
QuestionnaireDescription | Questionnaire.Description |
QuestionnaireChoices | Questionnaire.Choices |
QuestionnaireChoice | Questionnaire.Choice with ChoiceInput, ChoiceLabel, and ChoiceShortcut |
QuestionnaireInput | Questionnaire.Input |
QuestionnaireError | Questionnaire.Error |
QuestionnaireActions | なし。レイアウト専用です。独自のコンテナを使用してください。 |
QuestionnairePrevious, QuestionnaireSkip, QuestionnaireNext, QuestionnaireSubmit | Questionnaire.Previous, Questionnaire.Skip, Questionnaire.Next, Questionnaire.Submit |
スタイル付きの QuestionnaireChoice は、入力、ラベル、ショートカット、視覚的インジケーターをまとめて提供します。
スタイルなしパッケージでは、これらのパーツを自分で構成します。
基本的な使い方#
各 Item は 1 つのステップです。name でステップを識別し、回答用フォーム フィールドの名前になります。
Choice.value が送信される回答です。
const items = [
{
name: "prototype",
required: true,
prompt: "What should we prototype next?",
description: "Choose a direction or write your own.",
choices: [
{
value: "delegation",
label: "Delegation",
description: "Show how work moves to a specialist.",
},
{
value: "questions",
label: "Question prompts",
description: "Show choices while the interface waits.",
},
{ value: "both", label: "Both together" },
],
input: { label: "Another answer", placeholder: "Type another answer…" },
},
{
name: "detail",
required: false,
prompt: "How much detail should it include?",
description: "Skip this if you are not sure yet.",
choices: [
{ value: "focused", label: "Focused" },
{ value: "complete", label: "Complete flow" },
],
},
] as const"use client"
import * as React from "react"
import { Questionnaire } from "@shadcn/react/questionnaire"
export function ProjectQuestionnaire() {
function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault()
const formData = new FormData(event.currentTarget)
console.log({
prototype: formData.get("prototype"),
detail: formData.get("detail"),
})
}
return (
<Questionnaire.Root items={items} onSubmit={handleSubmit}>
<Questionnaire.Progress />
{items.map((question) => (
<Questionnaire.Item
key={question.name}
name={question.name}
required={question.required}
>
<Questionnaire.Title>{question.prompt}</Questionnaire.Title>
<Questionnaire.Description>
{question.description}
</Questionnaire.Description>
<Questionnaire.Choices>
{question.choices.map((choice) => (
<Questionnaire.Choice key={choice.value} value={choice.value}>
<Questionnaire.ChoiceInput />
<Questionnaire.ChoiceLabel>
<span>{choice.label}</span>
{"description" in choice ? (
<span>{choice.description}</span>
) : null}
</Questionnaire.ChoiceLabel>
<Questionnaire.ChoiceShortcut />
</Questionnaire.Choice>
))}
{"input" in question ? (
<Questionnaire.Input
aria-label={question.input.label}
placeholder={question.input.placeholder}
/>
) : null}
</Questionnaire.Choices>
<Questionnaire.Error />
</Questionnaire.Item>
))}
<Questionnaire.Previous />
<Questionnaire.Skip />
<Questionnaire.Next />
<Questionnaire.Submit />
</Questionnaire.Root>
)
}Item と Choice パーツとして描画するものと同じ items コレクションを Root に渡します。
これにより、項目の順序、進捗、アクションの表示、回答ショートカットをサーバーでレンダリングした HTML から利用できます。
複数選択#
multiple を指定すると、項目の固定選択肢がネイティブのチェックボックスになります。回答は FormData.getAll() で読み取ります。
アプリケーション データに multiple を保持し、描画する Item に渡してください。
const items = [
{
name: "signals",
required: true,
multiple: true,
prompt: "What should every update include?",
description: "Select all that apply.",
choices: [
{ value: "progress", label: "Progress" },
{ value: "decisions", label: "Decisions" },
{ value: "risks", label: "Risks" },
],
},
] as constitems.map((question) => (
<Questionnaire.Item
key={question.name}
name={question.name}
multiple={question.multiple}
required={question.required}
>
<Questionnaire.Title>{question.prompt}</Questionnaire.Title>
<Questionnaire.Description>
{question.description}
</Questionnaire.Description>
<Questionnaire.Choices>
{question.choices.map((choice) => (
<Questionnaire.Choice key={choice.value} value={choice.value}>
<Questionnaire.ChoiceInput />
<Questionnaire.ChoiceLabel>{choice.label}</Questionnaire.ChoiceLabel>
<Questionnaire.ChoiceShortcut />
</Questionnaire.Choice>
))}
</Questionnaire.Choices>
<Questionnaire.Error />
</Questionnaire.Item>
))const signals = new FormData(form).getAll("signals").map(String)自由入力の回答#
Input は自由入力の回答を追加し、ネイティブのテキスト入力を描画します。
const items = [
{
name: "prototype",
required: true,
prompt: "What should we prototype next?",
choices: [
{ value: "delegation", label: "Delegation" },
{ value: "questions", label: "Question prompts" },
],
input: {
label: "Another prototype direction",
placeholder: "Type another direction…",
},
},
] as constitems.map((question) => (
<Questionnaire.Item
key={question.name}
name={question.name}
required={question.required}
>
<Questionnaire.Title>{question.prompt}</Questionnaire.Title>
<Questionnaire.Choices>
{question.choices.map((choice) => (
<Questionnaire.Choice key={choice.value} value={choice.value}>
<Questionnaire.ChoiceInput />
<Questionnaire.ChoiceLabel>{choice.label}</Questionnaire.ChoiceLabel>
<Questionnaire.ChoiceShortcut />
</Questionnaire.Choice>
))}
<Questionnaire.Input
aria-label={question.input.label}
placeholder={question.input.placeholder}
/>
</Questionnaire.Choices>
<Questionnaire.Error />
</Questionnaire.Item>
))明示的なスキップ#
Skip は、任意項目を意図的に未回答のままにしたことを記録します。アプリケーションでスキップされた回答と
回答がない状態を区別する必要がある場合は、onStatusChange を使います。
"use client"
import * as React from "react"
import {
Questionnaire,
type QuestionnaireItemStatus,
} from "@shadcn/react/questionnaire"
export function PlanningQuestionnaire() {
const [timingStatus, setTimingStatus] =
React.useState<QuestionnaireItemStatus>("unanswered")
function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault()
const formData = new FormData(event.currentTarget)
console.log({
timing:
timingStatus === "skipped"
? { status: "skipped" }
: {
status: "answered",
value: formData.get("timing"),
},
})
}
return (
<Questionnaire.Root defaultItem="timing" onSubmit={handleSubmit}>
<Questionnaire.Item name="timing" onStatusChange={setTimingStatus}>
<Questionnaire.Title>
When should this be revisited?
</Questionnaire.Title>
<Questionnaire.Description>
Skip this if timing has not been decided.
</Questionnaire.Description>
<Questionnaire.Choices>
<Questionnaire.Choice value="week">
<Questionnaire.ChoiceInput />
<Questionnaire.ChoiceLabel>This week</Questionnaire.ChoiceLabel>
<Questionnaire.ChoiceShortcut />
</Questionnaire.Choice>
<Questionnaire.Choice value="cycle">
<Questionnaire.ChoiceInput />
<Questionnaire.ChoiceLabel>Next cycle</Questionnaire.ChoiceLabel>
<Questionnaire.ChoiceShortcut />
</Questionnaire.Choice>
</Questionnaire.Choices>
</Questionnaire.Item>
<Questionnaire.Skip />
<Questionnaire.Submit />
</Questionnaire.Root>
)
}回答ショートカット#
shortcuts="letters" または shortcuts="numbers" を使うと、有効な固定選択肢にキーを割り当てられます。
items が指定されている場合はその順序に従います。ヒントを表示したい場所に ChoiceShortcut を配置します。
<Questionnaire.Root shortcuts="letters">
<Questionnaire.Item name="review" required>
<Questionnaire.Title>What should the agent review?</Questionnaire.Title>
<Questionnaire.Choices>
<Questionnaire.Choice value="api">
<Questionnaire.ChoiceInput />
<Questionnaire.ChoiceLabel>Public API</Questionnaire.ChoiceLabel>
<Questionnaire.ChoiceShortcut />
</Questionnaire.Choice>
<Questionnaire.Choice value="tests">
<Questionnaire.ChoiceInput />
<Questionnaire.ChoiceLabel>Test coverage</Questionnaire.ChoiceLabel>
<Questionnaire.ChoiceShortcut />
</Questionnaire.Choice>
</Questionnaire.Choices>
</Questionnaire.Item>
</Questionnaire.Root>"letters" は A から Z を、"numbers" は 1 から 9 を割り当てます。
無効な選択肢はスキップされます。ショートカットで回答を選択しても、次の項目には進みません。
バリデーション#
Questionnaire は先へ進む前にアクティブな項目を検証し、フォーム送信時には有効なすべての項目を検証します。
- 必須項目は回答されると有効になります。
- 任意項目は回答されるか、明示的にスキップされると有効になります。
- 無効な項目と回答は無視されます。
required は「必須」という表示テキストを追加しません。必要に応じて Title または Description に記述してください。
検証に失敗すると、Questionnaire は無効な項目を表示したままにするか開き、回答へフォーカスします。メッセージを表示するには Error を追加します。
<Questionnaire.Item name="scope" required>
<Questionnaire.Title>
What should the project include? (Required)
</Questionnaire.Title>
<Questionnaire.Choices>{/* choices */}</Questionnaire.Choices>
<Questionnaire.Error />
</Questionnaire.Item>Error は項目が無効になるまで非表示です。既定メッセージを置き換えるには children を渡します。
<Questionnaire.Error>Please choose a project scope.</Questionnaire.Error>Error がなくても検証は動作します。描画されると、メッセージはスクリーン リーダーに通知されます。
Zod などの外部バリデーターを使う場合は、Item.invalid を設定し、Error にメッセージを描画して、
Root.item を最初の無効な項目へ移動します。
<Questionnaire.Root item={item} onItemChange={setItem} onSubmit={handleSubmit}>
<Questionnaire.Item invalid={Boolean(errors.detail)} name="detail" required>
<Questionnaire.Title>How much detail?</Questionnaire.Title>
<Questionnaire.Choices>{/* choices */}</Questionnaire.Choices>
<Questionnaire.Error>{errors.detail}</Questionnaire.Error>
</Questionnaire.Item>
</Questionnaire.Root>ナビゲーションの制御#
アクティブな項目を制御するには、item と onItemChange を渡します。
現在のチェックポイント: 変更範囲
const [item, setItem] = React.useState("scope")
<Questionnaire.Root item={item} onItemChange={setItem} onSubmit={handleSubmit}>
<Questionnaire.Item name="scope" required>
{/* question and answers */}
</Questionnaire.Item>
<Questionnaire.Item name="verification" required>
{/* question and answers */}
</Questionnaire.Item>
<Questionnaire.Previous />
<Questionnaire.Next>Next</Questionnaire.Next>
<Questionnaire.Submit>Submit</Questionnaire.Submit>
</Questionnaire.Root>既定値から再開する#
defaultItem、defaultChecked、defaultValue を使って保存済みの下書きを復元します。
<Questionnaire.Root defaultItem="verification">
<Questionnaire.Item name="scope" required>
<Questionnaire.Title>Which files are in scope?</Questionnaire.Title>
<Questionnaire.Choices>
<Questionnaire.Choice value="component" defaultChecked>
<Questionnaire.ChoiceInput />
<Questionnaire.ChoiceLabel>Component only</Questionnaire.ChoiceLabel>
</Questionnaire.Choice>
</Questionnaire.Choices>
</Questionnaire.Item>
<Questionnaire.Item name="verification" required>
<Questionnaire.Title>Any extra instructions?</Questionnaire.Title>
<Questionnaire.Input
aria-label="Extra instructions"
defaultValue="Run the package tests."
/>
</Questionnaire.Item>
<button type="reset">Reset draft</button>
</Questionnaire.Root>条件付き項目#
disabled を設定すると、現在のフローから項目を除外できます。無効な項目は進捗、ナビゲーション、検証、送信から除外されます。
const [runtime, setRuntime] = React.useState("local")
<Questionnaire.Root>
<Questionnaire.Item name="runtime" required>
<Questionnaire.Title>Where should the agent run?</Questionnaire.Title>
<Questionnaire.Choices>
<Questionnaire.Choice
value="local"
checked={runtime === "local"}
onChange={() => setRuntime("local")}
>
<Questionnaire.ChoiceInput />
<Questionnaire.ChoiceLabel>Locally</Questionnaire.ChoiceLabel>
</Questionnaire.Choice>
<Questionnaire.Choice
value="remote"
checked={runtime === "remote"}
onChange={() => setRuntime("remote")}
>
<Questionnaire.ChoiceInput />
<Questionnaire.ChoiceLabel>
Remote environment
</Questionnaire.ChoiceLabel>
</Questionnaire.Choice>
</Questionnaire.Choices>
</Questionnaire.Item>
<Questionnaire.Item name="region" disabled={runtime !== "remote"} required>
{/* remote-only question */}
</Questionnaire.Item>
</Questionnaire.Root>ナビゲーション状態#
ナビゲーション アクションは既定で有効です。そのため、次へまたは送信を実行すると検証エラーを表示できます。 アクションを自分で無効にしたい場合は、レンダー状態を使います。
<Questionnaire.Next
render={(props, state) => (
<button {...props} disabled={state.status === "unanswered"} />
)}
>
Next
</Questionnaire.Next>レンダー状態には visible、disabled、shortcut、アクティブな項目の status が含まれます。
見た目だけを変更する場合は、代わりに data-status を対象にします。
<Questionnaire.Next data-navigation-action>Next</Questionnaire.Next>[data-navigation-action][data-status="unanswered"] {
opacity: 0.5;
}カスタム進捗#
Progress は既定で Question {current} of {total} を描画します。要素や形式を変更するには render を使います。
<Questionnaire.Progress
aria-label="Setup progress"
render={(props, state) => (
<output {...props}>
Checkpoint {state.current} of {state.total}
</output>
)}
/>レンダー状態には current、total、first、last が含まれます。必要に応じてローカライズした aria-label を渡してください。
アニメーション付き項目#
進捗とナビゲーションを固定したまま、アクティブな項目をアニメーションさせます。
const itemClassName =
"data-active:animate-in data-active:fade-in-0 data-active:slide-in-from-bottom-2 data-active:duration-300 motion-reduce:animate-none"
<Questionnaire.Item
className={itemClassName}
name="task"
required
>
{/* ... */}
</Questionnaire.Item>非アクティブな項目はすぐに非表示になるため、表示時だけアニメーションさせます。
カードとの構成#
カードの周囲にルートを配置し、Title と Description をカード ヘッダーに描画します。
既定の legend を置き換えるため、タイトルに id を付けて項目の aria-labelledby と関連付けます。
const titleId = React.useId()
<Questionnaire.Root onSubmit={handleSubmit}>
<Card>
<Questionnaire.Item aria-labelledby={titleId} name="task" required>
<CardHeader>
<Questionnaire.Title id={titleId} render={<CardTitle />}>
What should the agent work on?
</Questionnaire.Title>
<Questionnaire.Description render={<CardDescription />}>
Choose the task that should be handled next.
</Questionnaire.Description>
<CardAction>
<Questionnaire.Progress />
</CardAction>
</CardHeader>
<CardContent>
<Questionnaire.Choices>{/* choices */}</Questionnaire.Choices>
<Questionnaire.Error />
</CardContent>
</Questionnaire.Item>
<CardFooter>
<Questionnaire.Next>Next</Questionnaire.Next>
<Questionnaire.Submit>Submit</Questionnaire.Submit>
</CardFooter>
</Card>
</Questionnaire.Root>ダイアログとの構成#
ダイアログの終了と Skip は分けて扱います。閉じる操作はフローをキャンセルし、スキップは意図的な未回答項目として記録します。
const titleId = React.useId()
<Dialog>
<DialogTrigger>Open clarification</DialogTrigger>
<DialogContent>
<Questionnaire.Root onSubmit={handleSubmit}>
<Questionnaire.Item aria-labelledby={titleId} name="scope" required>
<DialogHeader>
<Questionnaire.Progress />
<Questionnaire.Title id={titleId} render={<DialogTitle />}>
Which files are in scope?
</Questionnaire.Title>
<Questionnaire.Description render={<DialogDescription />}>
Choose how broadly the agent can update the workspace.
</Questionnaire.Description>
</DialogHeader>
<Questionnaire.Choices>{/* choices */}</Questionnaire.Choices>
<Questionnaire.Error />
</Questionnaire.Item>
<DialogFooter>
<DialogClose>Cancel</DialogClose>
<Questionnaire.Next>Next</Questionnaire.Next>
<Questionnaire.Submit>Send answer</Questionnaire.Submit>
</DialogFooter>
</Questionnaire.Root>
</DialogContent>
</Dialog>カスタム描画先#
render を使って、パーツの既定要素を置き換えます。要素を渡すか、状態が必要な場合は関数を使います。
<Questionnaire.Next render={<Button />}>Next</Questionnaire.Next>Root と Item は常に form と fieldset を描画します。Title が legend を描画しなくなる場合は、
id を付け、その ID を aria-labelledby で Item に渡してください。
プリミティブは data-slot を出力しません。スロットと視覚的インジケーターはスタイル付きラッパーが管理します。
ネイティブフォーム#
Root は常にネイティブ フォームを描画し、onSubmit、onReset、action、その他のフォーム props をサポートします。
Questionnaire を別のフォームの中にネストしないでください。
回答はネイティブ コントロールを通じてシリアライズされます。
FormData.get(itemName)は単一の回答を読み取ります。FormData.getAll(itemName)は複数の回答を読み取ります。- スキップされた項目は
FormDataに含まれません。 - スキップと未回答を区別するには
Item.onStatusChangeを使います。
Root は既定で noValidate を設定するため、ブラウザーの制約検証 UI ではなく Questionnaire.Error を使って検証します。
form.reset() は初期項目、既定の回答、スキップ状態、検証状態を復元します。
キーボード操作#
Questionnaire はネイティブのラジオボタン、チェックボックス、入力、ボタンの動作を基盤にしています。
| キー | 動作 |
|---|---|
Tab | 回答コントロールと表示中のアクション間でフォーカスを移動します。 |
Shift + Tab | 前のコントロールまたはアクションへフォーカスを移動します。 |
ArrowUp | 項目、固定回答、空のテキスト形式の自由入力から前の回答へ移動します。ネイティブ ラジオでは選択も行います。 |
ArrowDown | 項目、固定回答、空のテキスト形式の自由入力から次の回答へ移動します。ネイティブ ラジオでは選択も行います。 |
ArrowLeft | ラジオやテキスト入力の外側にフォーカスがある場合、前の項目へ移動します。 |
ArrowRight | アクティブな項目が回答済みまたはスキップ済みで、ラジオやテキスト入力の外側にフォーカスがある場合、次の項目へ移動します。 |
Space | ラジオを選択、チェックボックスを切り替え、またはフォーカス中のアクションを実行します。 |
Enter | 選択済みの選択肢または入力済みの入力から続行し、フォーカス中のアクションを実行します。 |
Command/Ctrl + Enter | アンケート内のどこからでも検証して続行するか、最後の項目を送信します。 |
テキスト フィールドへの入力中はショートカットと矢印ナビゲーションが一時停止します。
ルートの onKeyDown イベントを preventDefault すると、アンケートのキー処理が無効になります。
ナビゲーション アクションは既定で有効なため、操作を試みると検証フィードバックを表示できます。 未回答のアクションを無効化または再スタイルするには、ナビゲーション状態を参照してください。
アクセシビリティ#
Itemはfieldsetを描画します。Titleは既定で fieldset のlegendを描画します。カスタム描画先を使う場合は、idをaria-labelledbyで項目に関連付けます。DescriptionとアクティブなErrorはaria-describedbyで関連付けられます。- 無効な項目と回答コントロールは
aria-invalidを公開します。 Progressは現在値、最小値、最大値、テキスト値を持つ名前付き progressbar を描画します。- 固定選択肢にはネイティブのラジオボタンとチェックボックスを使います。
- 割り当てられたショートカット キーと利用可能なナビゲーションは
aria-keyshortcutsで公開されます。 - 非アクティブな項目とアクションは非表示かつ inert です。
- ナビゲーションでは、新しくアクティブになった fieldset にフォーカスします。
- 検証では、最初に利用可能な回答コントロールにフォーカスします。
- 無効な項目は進捗とナビゲーションから除外されます。
Input には常にアクセシブルな名前を付けます。明示的な id と表示ラベルを使います。
<Label htmlFor="other-answer">Other answer</Label>
<Questionnaire.Input
id="other-answer"
placeholder="Type another answer…"
/>デザイン上表示ラベルがない場合は、aria-label または aria-labelledby を使います。
<Questionnaire.Input
aria-label="Other answer"
placeholder="Type another answer…"
/>プレースホルダーはラベルではありません。
データ属性#
これらの属性をスタイル設定に使います。真偽値属性は true のときに存在し、false のときは存在しません。
Root と Progress#
| Data attribute | Value |
|---|---|
data-current | アクティブな項目の 1 始まりの位置。 |
data-total | 有効な項目の数。 |
data-first | 最初の項目に存在します。 |
data-last | 最後の項目に存在します。 |
data-shortcuts | Root で有効な場合の "letters" または "numbers"。 |
Item#
| Data attribute | Value |
|---|---|
data-active | アクティブなときに存在します。 |
data-status | "unanswered"、"answered"、"skipped" のいずれか。 |
data-required | 必須のときに存在します。 |
data-multiple | 複数選択のときに存在します。 |
data-disabled | 無効なときに存在します。 |
data-invalid | 検証に失敗した後に存在します。 |
Choice#
| Data attribute | Value |
|---|---|
data-type | "radio" または "checkbox"。 |
data-checked | 選択されているときに存在します。 |
data-unchecked | 選択されていないときに存在します。 |
data-disabled | 無効なときに存在します。 |
data-invalid | 項目が無効なときに存在します。 |
data-shortcut | 割り当てられた文字または数字。 |
Choices#
| Data attribute | Value |
|---|---|
data-shortcuts | 有効な場合の "letters" または "numbers"。 |
Input#
| Data attribute | Value |
|---|---|
data-filled | 入力に空でないテキストがあるときに存在します。 |
data-empty | 入力に回答テキストがないときに存在します。 |
data-disabled | 無効なときに存在します。 |
data-invalid | 項目が無効なときに存在します。 |
Error#
| Data attribute | Value |
|---|---|
data-invalid | エラーがアクティブな間に存在します。 |
Previous、Skip、Next、Submit#
| Data attribute | Value |
|---|---|
data-visible | アクションがアクティブな項目に適用されるときに存在します。 |
data-hidden | アクションが適用されないときに存在します。 |
data-disabled | 無効なときに存在します。 |
data-shortcut | 有効で表示中の Next または Submit における "Enter"。 |
data-status | アクティブな項目の "unanswered"、"answered"、または "skipped"。 |
Title と Description に状態属性はありません。スタイルなしパーツは data-slot を出力しません。
API リファレンス#
Questionnaire.Root#
フォームと調整を担うルートです。
| Prop | Type | Default | Description |
|---|---|---|---|
item | string | - | アクティブな項目名を制御します。 |
defaultItem | string | first enabled item | 初期状態でアクティブにする項目名です。 |
items | readonly QuestionnaireItemDefinition[] | - | サーバー レンダリングと項目順序に使う任意の項目データです。 |
onItemChange | (item: string) => void | - | ナビゲーションで別の項目が要求されたときに呼び出します。 |
shortcuts | "letters" | "numbers" | - | 定義または描画された DOM の順序で、範囲付きの回答ショートカットを割り当てます。 |
noValidate | boolean | true | アンケートの検証を維持しながら、ネイティブの制約検証 UI を無効にします。 |
onSubmit | FormEventHandler<HTMLFormElement> | - | すべての項目の検証後に実行されるネイティブ フォーム送信ハンドラーです。 |
onReset | FormEventHandler<HTMLFormElement> | - | ネイティブのリセット ハンドラーです。アンケートのリセットを止めるには preventDefault します。 |
Root は current、total、first、last、shortcuts をデータ属性で公開します。
任意のコレクション型は @shadcn/react/questionnaire からエクスポートされます。
type QuestionnaireChoiceDefinition = {
value: string
disabled?: boolean
}
type QuestionnaireItemDefinition = {
name: string
required?: boolean
disabled?: boolean
choices?: readonly QuestionnaireChoiceDefinition[]
}Questionnaire.Progress#
有効な項目コレクション内の位置です。
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | Question {current} of {total} | 進捗コンテンツをカスタマイズします。 |
aria-label | string | Questionnaire progress | progressbar のアクセシブルな名前です。 |
render | ReactElement | (props, state) => ReactElement | <div> | 進捗状態を持つカスタム描画先です。 |
レンダー状態には current、total、first、last が含まれます。
Questionnaire.Item#
アンケートの 1 つのステップです。
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | required | 一意な項目識別子であり、ネイティブ フォーム フィールド名です。 |
invalid | boolean | false | 外部バリデーターによって項目を無効としてマークします。 |
required | boolean | false | 回答を必須にし、Skip を無効にします。 |
multiple | boolean | false | 固定選択肢をチェックボックスとして描画します。 |
disabled | boolean | false | 項目を進捗とナビゲーションから除外します。 |
onStatusChange | (status: QuestionnaireItemStatus) => void | - | "unanswered"、"answered"、"skipped" の変化を監視します。 |
Item は active、disabled、invalid、multiple、required、status をデータ属性で公開します。
Item 名は Root 内で一意でなければなりません。名前は fieldset ではなく回答コントロールに属します。
Questionnaire.Title#
項目のタイトルです。既定ではセマンティックな legend を描画します。
| Prop | Type | Default | Description |
|---|---|---|---|
render | ReactElement | render function | <legend> | カスタム描画先です。その id を項目の aria-labelledby と組み合わせます。 |
Questionnaire.Description#
aria-describedby で項目に関連付ける補足テキストです。
| Prop | Type | Default | Description |
|---|---|---|---|
render | ReactElement | render function | <p> | カスタム描画先です。 |
Questionnaire.Choices#
固定回答と自由入力回答のレイアウト コンテナです。
| Prop | Type | Default | Description |
|---|---|---|---|
render | ReactElement | render function | <div> | カスタム描画先です。 |
レンダー状態には shortcuts が含まれます。
Questionnaire.Choice#
固定回答のコンテナです。中に ChoiceInput、ChoiceLabel、必要に応じて ChoiceShortcut を 1 つずつ配置します。
既定の <label> により、行全体がネイティブ コントロールに関連付けられます。
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | required | ネイティブ回答値です。 |
checked | boolean | - | 選択状態を制御します。 |
defaultChecked | boolean | false | 初期選択状態です。 |
disabled | boolean | false | ネイティブ回答コントロールを無効にします。 |
onChange | ChangeEventHandler<HTMLInputElement> | - | ネイティブ入力の変更ハンドラーです。 |
render | ReactElement | (props, state) => ReactElement | <label> | 選択状態を持つカスタム描画先です。 |
レンダー状態には checked、disabled、invalid、shortcut、type が含まれます。
Questionnaire.ChoiceInput#
所属する Choice のネイティブ ラジオボタンまたはチェックボックスです。Questionnaire が選択、フォーム送信、検証、
キーボード操作に必要な props を提供します。className、id、ref、render、その他競合しないネイティブ入力 props も受け取ります。
ChoiceInput は Choice の内部で使う必要があります。レンダー状態は Choice と同じです。
Questionnaire.ChoiceLabel#
固定選択肢の表示ラベル コンテンツです。Choice のラベル内に <span> を描画し、ネイティブ span props と render を受け取ります。
Questionnaire.ChoiceShortcut#
固定選択肢の表示ショートカットです。割り当てられた文字または数字を含む <span> を描画し、選択肢にショートカットがない場合は非表示のままです。
ネイティブ span props と render を受け取り、レンダー状態には shortcut が含まれます。
Questionnaire.Input#
自由入力の回答です。ネイティブの name は所属する項目が管理します。
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | number | readonly string[] | - | ネイティブ入力値を制御します。 |
defaultValue | string | number | readonly string[] | - | 初期ネイティブ入力値です。 |
disabled | boolean | false | 入力を無効にします。 |
onChange | ChangeEventHandler<HTMLInputElement> | - | ネイティブ入力の変更ハンドラーです。 |
type | QuestionnaireInputType | "text" | "email"、"number"、"date" などのテキスト入力型です。 |
render | ReactElement | (props, state) => ReactElement | <input> | 入力状態を持つカスタム描画先です。 |
レンダー状態には disabled、filled、invalid が含まれます。
Questionnaire.Error#
検証メッセージです。項目の検証に失敗するまで非表示です。
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | contextual message | カスタム検証メッセージです。 |
render | ReactElement | (props, state) => ReactElement | <p> | 無効状態を持つカスタム描画先です。 |
ナビゲーション アクション#
Previous、Skip、Next、Submit はネイティブ ボタンを描画し、表示状態が変わってもマウントされたままです。
| Part | Default type | Visible when | Disabled when |
|---|---|---|---|
Previous | "button" | 最初の項目ではないとき。 | 利用側が disabled を設定します。 |
Skip | "button" | アクティブな項目が任意のとき。 | 利用側が disabled を設定します。 |
Next | "button" | 最後の項目ではないとき。 | 利用側が disabled を設定します。 |
Submit | "submit" | 最後の項目のとき。 | 利用側が disabled を設定します。 |
各パーツはネイティブ ボタン props と次の props を受け取ります。
| Prop | Type | Description |
|---|---|---|
render | ReactElement | (props, state) => ReactElement | ナビゲーション状態を持つカスタム描画先です。 |
レンダー状態には visible、disabled、shortcut、アクティブな項目の status が含まれます。
On This Page
インストールインポート構成スタイル付きバージョン基本的な使い方複数選択自由入力の回答明示的なスキップ回答ショートカットバリデーションナビゲーションの制御既定値から再開する条件付き項目ナビゲーション状態カスタム進捗アニメーション付き項目カードとの構成ダイアログとの構成カスタム描画先ネイティブフォームキーボード操作アクセシビリティデータ属性Root と ProgressItemChoiceChoicesInputErrorPrevious、Skip、Next、SubmitAPI リファレンスQuestionnaire.RootQuestionnaire.ProgressQuestionnaire.ItemQuestionnaire.TitleQuestionnaire.DescriptionQuestionnaire.ChoicesQuestionnaire.ChoiceQuestionnaire.ChoiceInputQuestionnaire.ChoiceLabelQuestionnaire.ChoiceShortcutQuestionnaire.InputQuestionnaire.Errorナビゲーション アクション