affectUI › Components › Chat
AI Answer
Streamed answer with source cards, citation chips that preview their source, copy, regenerate, feedback and follow-ups.
Part of affectUI Pro. Install: npx shadcn@latest add https://www.affectui.com/r/ai-answer.json · Import from @/components/ui/ai-answer
When to use
- Answers from an assistant that searched your docs, the web or connected tools and should show where each claim comes from
- Research, support or knowledge-base products where people need to check the source before they act
When not to use
- Casual chat without sources – a plain message bubble is lighter
- Long documents or code – the answer is made for a few paragraphs and lists
Usage
import { AIAnswer, type AnswerSource } from "@/components/ui/ai-answer";
const sources: AnswerSource[] = [
{ name: "Notion", title: "Offsite plan – shortlist and budget", href: "https://notion.so/…", snippet: "Budget €4,500 for three nights…" },
{ name: "Slack", title: "#team-offsite – who can make which dates", href: "https://slack.com/…" },
];
export function Answer({ text, done }: { text: string; done: boolean }) {
return (
<AIAnswer
question="Where should we hold the team offsite?"
sources={sources}
// Blank lines: paragraphs · "- ": list · **bold** · [1] or [1,2]: citations (1-based)
answer={text}
streaming={!done}
onRegenerate={() => regenerate()}
onFeedback={(value, reason) => track("answer_feedback", { value, reason })}
/>
);
}Props
| Name | Type | Default | Description |
|---|---|---|---|
question | string | Shown as the title above the sources | |
sources | AnswerSource[] | Each { title, name, href?, icon?, snippet? }; name is the short label on the citation chip | |
answer | string | Blank lines make paragraphs, lines starting with "- " a list, **bold**, [1] or [1,3] cite sources (1-based). It may grow while streaming; a different text starts over | |
streaming | boolean | false | More text is still coming from your model – keeps the cursor going once it has caught up |
animate | boolean | true | Stream the text in; false shows it at once |
speed | number | 38 | Words per second while streaming in |
followUps | string[] | Related questions shown below the finished answer | |
onFollowUp | (question: string) => void | A follow-up was clicked | |
onRegenerate | () => void | Regenerate was clicked – the answer streams in again; pass a new answer to replace it | |
onStop | () => void | Stop was clicked while writing – cancel your request here | |
onFeedback | (value: "up" | "down", reason?: string) => void | Thumbs up, or thumbs down with the reason that was picked | |
feedbackReasons | string[] | ["Not accurate", "Wrong source", "Too long", "Out of date"] | Reasons offered after a thumbs down |
onCopy | (text: string) => void | Called with the copied text: the answer without markup plus a numbered source list | |
className | string | Extra class on the root |
Keyboard
- Tab: Moves through source cards, citation chips, follow-ups and actions
- Esc: Closes the source preview of the focused chip
Accessibility
- Citation chips are buttons named after their sources; the preview is a tooltip linked to the chip
- The answer is marked busy while it streams, so screen readers read it once it's complete
- Copy, feedback and status changes are announced in a polite live region
Responsive
- Fills its container up to 640px; source cards scroll sideways on narrow screens
- Tap a citation chip to open its preview on touch screens
- Dark mode built in: switches when an ancestor (usually <html>) has the class dark or data-theme="dark"
Requirements
- React 19
Related
- Thinking State – AI working panel with a live timer, searched sources and thinking steps that appear one by one
- Chat Composer – Prompt composer with model picker, voice input, app connections and approval request
- Comment Thread – One comment with replies – an assistant reports what it did, folds open details and answers @mentions
Guides
- React components for AI chat interfaces – What an AI chat UI needs – composer, streaming answers, thinking states, tool calls, citations, message actions – and React components for each.
- Streaming AI responses in React without layout shift – How to render streamed LLM answers in React so the page doesn't jump – stable containers, a clear thinking state, smooth text, and actions that appear in place.