KQ-2051 · ASK/BACK
Ask Back
An assistant thread that clarifies before it writes: the open request gets two to four questions as chip sets, and each settled chip lifts off and flies into its slot on the pinned brief on springs.glide, its box morphing to the slot as the value cross-fades in. When the last answer lands the brief is stamped Complete on springs.recoil and the real answer streams in; questions deal in on springs.snap and chips press on springs.flick. Each chip set is a radiogroup (arrows move the pick, Enter settles it and moves on), Skip and Write it now answer on stated assumptions, a brief slot reopens its question and Backspace in an empty composer reopens the last one.
Q3 report
Fernworks Model 3 · asks before it answers
Arrow keys move between choices, Enter settles one. Backspace in an empty message box reopens the last answer.
1 of 4 settled · waiting on period
Install
One command — the source lands in your repo. Or copy it from the Code tab.
$ pnpm dlx shadcn@latest add @kinetiq/ask-back
Props
- request
- string
- default "Draft the Q3 report for Basinworks."
- The visitor's open request at the top of the thread.
- questions
- AskBackQuestion[]
- default defaultAskBackQuestions
- Two to four questions, each with prompt, short brief label, options, an assumption used when skipped and an optional why line.
- value / defaultValue
- AskBackAnswers
- default {}
- Controlled or initial answers: question id to { value, label, assumed? }.
- onValueChange
- (answers: AskBackAnswers) => void
- default —
- Fires from the press, key, skip or reopen that changed the answers.
- onAnswer
- (questionId: string, answer: AskBackAnswer, answers: AskBackAnswers) => void
- default —
- A question was answered by a chip or in the visitor's own words.
- onSkip
- (questionId: string, assumedValue: string) => void
- default —
- A question was skipped and answered on its assumption.
- onSkipAll
- (answers: AskBackAnswers) => void
- default —
- Write it now answered every open question on its assumption.
- onBriefEdit
- (questionId: string) => void
- default —
- A brief slot was pressed and its question reopened.
- onComplete
- (answers: AskBackAnswers) => void
- default —
- Every question is settled; the answer starts to stream.
- onSend
- (text: string) => void
- default —
- A follow-up was sent after the brief was complete.
- answer
- string | ((answers: AskBackAnswers) => string)
- default defaultAskBackAnswer
- The real answer, streamed once the brief is complete.
- streamRate
- number
- default 22
- Words a second while the answer streams.
- chipStyle
- "pill" | "tile" | "line"
- default "pill"
- Rounded chips, boxed tiles with a detail line, or underlined text options.
- briefPlacement
- "dock" | "top" | "side"
- default "dock"
- Brief pinned above the composer, under the header, or in a side column on wide surfaces.
- accent
- string
- default "var(--accent-bright)"
- Chosen chips, the flight and the stamp — any CSS colour.
- model
- string
- default "Fernworks Model 3"
- The model answering, shown in the header.
- title
- string
- default "Q3 report"
- The surface's heading and accessible name.
- status
- "ready" | "loading" | "error"
- default "ready"
- Whether the questions have arrived.
- onRetry
- () => void
- default —
- Try again was pressed after the questions failed to load.
- height
- number
- default 520
- Height of the surface in px; the thread scrolls inside it.
- disabled
- boolean
- default false
- Read only: nothing can be answered, skipped or sent.
- className
- string
- default —
- Classes for the surface.
| Prop | Type | Default | Description |
|---|---|---|---|
| request | string | "Draft the Q3 report for Basinworks." | The visitor's open request at the top of the thread. |
| questions | AskBackQuestion[] | defaultAskBackQuestions | Two to four questions, each with prompt, short brief label, options, an assumption used when skipped and an optional why line. |
| value / defaultValue | AskBackAnswers | {} | Controlled or initial answers: question id to { value, label, assumed? }. |
| onValueChange | (answers: AskBackAnswers) => void | — | Fires from the press, key, skip or reopen that changed the answers. |
| onAnswer | (questionId: string, answer: AskBackAnswer, answers: AskBackAnswers) => void | — | A question was answered by a chip or in the visitor's own words. |
| onSkip | (questionId: string, assumedValue: string) => void | — | A question was skipped and answered on its assumption. |
| onSkipAll | (answers: AskBackAnswers) => void | — | Write it now answered every open question on its assumption. |
| onBriefEdit | (questionId: string) => void | — | A brief slot was pressed and its question reopened. |
| onComplete | (answers: AskBackAnswers) => void | — | Every question is settled; the answer starts to stream. |
| onSend | (text: string) => void | — | A follow-up was sent after the brief was complete. |
| answer | string | ((answers: AskBackAnswers) => string) | defaultAskBackAnswer | The real answer, streamed once the brief is complete. |
| streamRate | number | 22 | Words a second while the answer streams. |
| chipStyle | "pill" | "tile" | "line" | "pill" | Rounded chips, boxed tiles with a detail line, or underlined text options. |
| briefPlacement | "dock" | "top" | "side" | "dock" | Brief pinned above the composer, under the header, or in a side column on wide surfaces. |
| accent | string | "var(--accent-bright)" | Chosen chips, the flight and the stamp — any CSS colour. |
| model | string | "Fernworks Model 3" | The model answering, shown in the header. |
| title | string | "Q3 report" | The surface's heading and accessible name. |
| status | "ready" | "loading" | "error" | "ready" | Whether the questions have arrived. |
| onRetry | () => void | — | Try again was pressed after the questions failed to load. |
| height | number | 520 | Height of the surface in px; the thread scrolls inside it. |
| disabled | boolean | false | Read only: nothing can be answered, skipped or sent. |
| className | string | — | Classes for the surface. |