I can tailor the product design. Answer three quick questions first.
Questionnaire
Answer structured questions one step at a time and see when the receiver accepts the response.
Preview
Progress counts valid answers and optional skips. It does not count the current step. Choice questions can add an editable final row with custom without exposing a visible “Other” label; custom answers are typed records with a stable question-scoped identity, so text never collides with a known option. After acknowledgement, a valid submitted response may also count an explicitly stored empty optional answer; an empty questionnaire stays incomplete. Cancelled and expired requests remain readable with their retained response or drafts, while a submitted request without a response says that the response is unavailable.
Design guidance
In a chat, place Questionnaire directly in ChatFooter in place of Composer. It fills the same available width. Keep the editable questionnaire outside Message; put the acknowledged QuestionnaireRecord in one user Message. The caller restores the preserved draft and textarea focus after acknowledgement. See SDK integration for tool-result and approval wiring.
Accessibility
Each question has a real legend or Field label. Errors link to the invalid control and focus the first invalid question after validation. Back, Next, Skip, and Submit are native buttons; terminal responses are read-only and cancelled or expired requests are inert.
Installation
Install
Source files
Basic usage
Structures
Examples
Design intake
Answer a short design-intake conversation with one question visible at a time.
Required single-choice
Move through required choices with the native RadioGroup and explicit arrow action.
Multiple choices
Toggle one or more options with the shared Checkbox owner, then continue explicitly.
Freeform
Enter a required text answer with the shared Field and Input owners.
Optional skip
Skip an optional question while preserving the skipped id in the response.
Validation
Submit without a required choice to show the linked error and focus the first invalid control.
Failed send and acknowledgement
A rejected send retains the draft. A later success waits for the parent to confirm receipt.
Submitted record
Show the accepted response as a read-only record.
Cancelled request
Keep retained answers readable after the request is cancelled; the record has no interactive controls.
Expired request
Keep an expired request readable and inert.
Long and narrow content
Wrap long translated labels and notes without clipping the controls.
Unavailable response
Keep every question readable when the conversation cannot receive an answer.
Questions
- How should we deliver the replacement?
- No answer recorded.
- What else should we know?
- No answer recorded.
Responses are unavailable for this request.
Complete conversation
The conversation owner turns one acknowledged response into a readable user answer and restores its composer.
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
questionsrequired | readonly QuestionDefinition[] | The stable-id questions to answer. | |
value | QuestionnaireAnswers | undefined | Controls the draft answers. | |
defaultValue | QuestionnaireAnswers | undefined | Seeds an uncontrolled draft. | |
onValueChange | (value: QuestionnaireAnswers) => void | Receives reconciled draft answers. | |
onSubmitrequired | (response: QuestionnaireResponse) => void | Promise<void> | Receives a validated response. | |
status | editing | submitting | submitted | cancelled | expired | editing | Reports caller-owned lifecycle state. |
response | QuestionnaireResponse | undefined | Provides the accepted response for read-only display. | |
error | string | undefined | Returns a controlled submission to editing with retained answers. | |
label | string | Questionnaire | Names the form. |
QuestionDefinition.custom adds a final editable row to a single- or multiple-choice question. Set it to true, or provide its placeholder and maximum length as an object. The submitted value is { type: "custom", id: "custom:<question-id>", value: "..." }; multiple-choice answers contain this record beside known option values.
| Prop | Type | Default | Description |
|---|---|---|---|
questionsrequired | readonly QuestionDefinition[] | The stable-id questions to display. | |
response | QuestionnaireResponse | undefined | Retains submitted or cancelled answers when available. | |
statusrequired | submitted | cancelled | expired | unavailable | Selects the read-only record state. |
QuestionnaireRecord displays submitted, cancelled, expired, or unavailable answers as a read-only record and forwards native div props and its ref.