Audit our checkout page for accessibility issues and file what you find.
Conversation
The Agent kit is a set of composable components for AI products: chat, copilots and agents. They use the same tokens, Brand, Color and Radius modes as the rest of Atomus, plus a small AI layer (--color-bg-ai-subtle, --color-border-ai, --color-text-ai, --gradient-ai) that marks AI content without decorating anything else. Nothing depends on an AI SDK: each component takes plain props such as a growing string and a status, so it works with the Vercel AI SDK, LangChain, your own backend or an MCP host.
Pick a prompt starter below. The demo streams a simulated reply: the agent reasons, runs a tool, asks for your approval, then answers with citations. Try Deny, Edit, or the Stop button while it writes.
How can I help with your design system?
Ask about tokens and components, or let the assistant audit a page. It asks before it changes anything.
Add the AI chat screen (this pattern as a block) to a shadcn project
npx shadcn@latest add https://docs.atomus.io/r/ai-chat.jsonOpen in v0Installs the component source, its CSS and the Atomus tokens into components/atomus/. How the registry works
Finished thread
Section titled “Finished thread”In Figma
Section titled “In Figma”From guidelines/components/ai-message.md
Properties, variants and anatomy of the Figma components. React props use the same names.
Conversation
Section titled “Conversation”The pattern that puts the Agent kit together: a header with the assistant’s name, AI label and Context meter; a scrolling thread of Messages; and a Prompt input docked at the bottom. An empty thread shows a welcome state with prompt starters (Suggestions, variant="cards"). There is no Conversation component: compose it from the parts.
Anatomy
- Header: assistant name, AI label with an explanation, Context meter, New chat.
- Thread:
role="log"region, max width about 720px,spacing-3xlbetween messages. - Welcome state: AI mark, one-line title, one sentence on what the assistant can do, 2–4 prompt starters.
- Composer: Prompt input with the Model selector, and a disclaimer.
- Follow-up Suggestions under the latest answer.
Accessibility
- Give the thread
role="log"and an accessible name. Turn its own live announcements off (aria-live="off") when Streaming text announces replies, so nothing is read twice. - Make the scrolling thread focusable (
tabIndex={0}) so keyboard users can scroll it. - Keep focus in the Prompt input after sending; never move it to the new reply.
- Scroll new content into view inside the thread, not the whole page.
There is no Conversation component — compose the parts. A minimal thread with any streaming backend:
import { Message, Reasoning, ToolCall, StreamingText, Sources, PromptInput, Suggestions } from '@stanvision/atomus-react';
<div role="log" aria-label="Conversation" aria-live="off" tabIndex={0} className="thread"> {messages.length === 0 ? ( <Suggestions variant="cards" suggestions={starters} onSelect={send} /> ) : messages.map((m) => ( <Message key={m.id} role={m.role} name={m.role === 'user' ? 'You' : 'Atomus Assistant'} status={m.status} copyText={m.text} onRegenerate={m.role === 'assistant' ? () => regenerate(m.id) : undefined}> {m.reasoning ? <Reasoning status={m.thinking ? 'thinking' : 'done'} duration={m.thoughtFor} steps={m.steps} /> : null} {m.tools.map((t) => <ToolCall key={t.id} name={t.name} status={t.status} input={t.input} output={t.output} />)} <StreamingText text={m.text} streaming={m.status === 'streaming'} /> {m.sources ? <Sources sources={m.sources} /> : null} </Message> ))}</div><PromptInput status={busy ? 'streaming' : 'ready'} onSubmit={send} onStop={stop} />Adapting an AI SDK
Section titled “Adapting an AI SDK”- Map the SDK’s message parts to components: text →
StreamingText, reasoning →Reasoning, tool calls →ToolCall, tool calls that need approval →Approval, source parts →SourcesandInlineCitation. - Map its status to
PromptInput status(submitted,streaming,ready,error) and its stop function toonStop. - Adapters for popular SDKs may ship later as optional packages; the components will not change.
Design guidance
Section titled “Design guidance”From the Figma guidelines.
Do
- Say what the assistant can and can’t do in the welcome state.
- Ask before acting: route every write or send through an Approval.
- Keep one primary button per view: Send, or Approve while an approval is pending.
Forbidden
- Never start a conversation with a wall of starters — four at most.
- Never auto-scroll while the person is reading earlier messages.
- Never stream into a region that also announces every token.
React API
Section titled “React API”Generated from react/src/components by scripts/gen-react-api.mjs — the same tables agents read in guidelines/components/ai-message.md.
Use only these props; anything else is not part of the API.
Message
Section titled “Message”Figma: Message — one turn in a conversation. Every message is an <article> named by its speaker, so screen-reader users always know who said what (Primer: speaker clarity).
import { Message } from '@stanvision/atomus-react'; — source: react/src/components/ai/Message.tsx
| Prop | Type | Default | Description |
|---|---|---|---|
role |
'user' | 'assistant' | 'system' | 'tool' |
'assistant' |
Figma: Role — who is speaking. Sets layout, label and default name. |
status |
'streaming' | 'done' | 'error' | 'stopped' |
'done' |
Figma: Status — streaming keeps the message busy; error and stopped show an inline notice. |
name |
string |
— | Figma: Name — the speaker (“You”, “Atomus AI”, “Research agent”). Always announced to screen readers. |
avatar |
ReactNode |
— | Figma: Avatar — an Avatar or logo; assistants default to the AI mark. |
showName |
boolean |
— | Figma: Show name — show the speaker name visually (screen readers always get it). Defaults to true except for user messages. |
aiLabel |
boolean |
true |
Figma: AI label — shows the AI label next to an assistant’s name. |
time |
string |
— | Figma: Timestamp — display text (“2:41 PM”) |
dateTime |
string |
— | Machine-readable time (ISO 8601) for the <time> element |
children |
ReactNode |
— | Figma: Content |
copyText |
string |
— | Plain text of the message for the Copy action; Copy is hidden without it. |
onRegenerate |
() => void |
— | Figma: Regenerate — assistant messages; also the retry action for status="error". |
onEdit |
() => void |
— | Figma: Edit — user messages |
branch |
MessageBranch |
— | Figma: Branch — ‹ 1/3 › switcher between regenerated or edited versions |
actions |
ReactNode |
— | Extra actions after the built-in ones (e.g. Feedback) |
actionsVisibility |
'always' | 'hover' |
'always' |
Figma: Actions visibility — always, or on hover and keyboard focus (always shown on touch screens) |
errorMessage |
ReactNode |
'Something went wrong while generating this response.' |
Error text for status="error" |
Also accepts every native HTML attribute (id, role …), except role, which is replaced above.
MessageBranch:
| Field | Type | Description |
|---|---|---|
index |
number |
1-based number of the version shown |
count |
number |
How many versions exist |
onPrevious? |
() => void |
Shows the previous version |
onNext? |
() => void |
Shows the next version |