Question
A multiple-choice question from the agent. Pick with number or arrow keys, or type your own answer.
Loading preview…
Install
- 1
Run this command in your Tailwind CSS project. It adds
components/ai/question-default.tsxand installs its dependencies.$ npx shadcn@latest add https://gradientdeck.com/ai-components/r/question-default.json
Usage & API
Example
import { Question } from "@/components/ai/question-default"
<Question
question="…"
options={[]}
onSubmit={() => {}}
/>Props Question
| Prop | Type & description | Required |
|---|---|---|
question | string | Required |
options | QuestionOption[] | Required |
allowOther | booleanAdds an "Other" choice with a text field. | Optional |
onSubmit | (answer: string) => void | Required |
onSkip | () => voidShows a "Skip" button that hands the composer back without answering. | Optional |
Dependencies
- React
- Tailwind CSS
- motion
- lucide-react
Implementation notes
The box is a radiogroup labeled by the question. Each option is a radio button showing an index, the label, and hint if you passed one. The selected row is highlighted. Keys 1 through 9 select a row when focus is not in the text field, and only if that index exists. Arrow keys move the selection. Arrow up is ignored while the other field is focused. Enter submits. Escape calls onSkip, and only if you passed it. The footer note reads that the number keys pick, and mentions Esc when skip exists. Something else is included unless allowOther is false. Submitting calls onSubmit with the label string, or with the trimmed custom text. Skip calls onSkip and does not call onSubmit.
Example
import { QuestionCards } from "@/components/ai/question-cards"
<QuestionCards
question="…"
choices={[]}
onSubmit={() => {}}
/>Props QuestionCards
| Prop | Type & description | Required |
|---|---|---|
question | string | Required |
choices | QuestionChoice[] | Required |
onSubmit | (id: string) => void | Required |
Dependencies
- React
- Tailwind CSS
- lucide-react
Implementation notes
The fieldset lists choices as radios. The visible index is replaced by a check on the selected row. Title and description are both shown. The footer reads Waiting for your answer for as long as the list is mounted. The submit button is disabled with no selection, and its accessible name is Submit answer. onSubmit receives the id. There is no onSkip, no allowOther and no hint field. Changing a submitted answer is not built in. Unmount the list and show the chosen title yourself if the thread should record the decision.
Choosing a layout
Use a question when the agent is blocked on a preference: where to keep a queue, whether existing sessions stay valid, which of two designs to follow. The options should be answers the agent can act on. hint, on the composer form, is the short consequence under a label. description, on the decision list, is the longer one. Prefer the composer form when it should replace the input until the person answers, including the case where they need to type something you did not list. Pass onSkip only when skipping is a real outcome and your code will resume without an answer.
Prefer the decision list when the choice should remain in the thread as a fieldset, with a description on every row, and you do not want a free-text path. Tool approval is the wrong control when nothing is about to be executed. Approval is deny, once or always on a command. A plan is the wrong control when the person is not accepting a sequence of work. After onSubmit, replace the question with the reply that uses the answer. The composer form does not draw a resolved state of its own. The decision list does not either, aside from the selected radio while it is still mounted.
What does onSubmit receive?
On the composer question, the selected option's label, or the trimmed contents of Your answer when Something else is selected. The option id is not included. On the decision list, onSubmit receives the choice id and not the title. If you need the title later, look it up from the id you were given.
How do I let someone decline to answer?
Pass onSkip to the composer question. That shows Skip, and Escape calls it. Leave onSkip unset and there is no Skip button and Escape does nothing. The decision list cannot skip. It submits only a selected id. allowOther false removes Something else, which is a different thing: the person must still pick one of your options.