Skip to content

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.

Atomus Assistant

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.

AI can make mistakes. Check important information.

Conversation · Message + Reasoning + ToolCall + Approval + StreamingText + Sources + Suggestions + PromptInputLive · light and dark follow the theme switch

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 v0

Installs the component source, its CSS and the Atomus tokens into components/atomus/. How the registry works

Atomus Assistant
Kristina

Audit our checkout page for accessibility issues and file what you find.

Atomus AssistantAI
Thought for 8s

Medium risklinear.create_issues

File 3 issues in Linear?

Creates three issues in the Checkout project and assigns them to the design team.

1. Pay button: label contrast 3.1:1 (needs 4.5:1) 2. Card number: placeholder used as label 3. Payment error: focus jumps to page top

Approved

I audited the checkout page and found 3 issues that block WCAG 2.2 AA. The Pay button label has a contrast of 3.1:1, below the 4.5:1 minimum for text 1w3.orgUnderstanding SC 1.4.3: Contrast (Minimum)The visual presentation of text and images of text has a contrast ratio of at least 4.5:1.. The card-number field uses its placeholder as its only label, so screen readers announce it as “edit text” 2w3.orgUnderstanding SC 3.3.2: Labels or InstructionsLabels or instructions are provided when content requires user input. A placeholder is not a label.. After a payment error, focus jumps to the top of the page instead of the error message 3w3.orgUnderstanding SC 2.4.3: Focus OrderFocusable components receive focus in an order that preserves meaning and operability.. I filed all three in Linear with fixes that use the Atomus tokens and the Input component.
Version 2 of 2

AI can make mistakes. Check important information.

The same conversation after the reply — feedback, branches, sources and follow-upsLive · light and dark follow the theme switch

From guidelines/components/ai-message.md

Properties, variants and anatomy of the Figma components. React props use the same names.

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

  1. Header: assistant name, AI label with an explanation, Context meter, New chat.
  2. Thread: role="log" region, max width about 720px, spacing-3xl between messages.
  3. Welcome state: AI mark, one-line title, one sentence on what the assistant can do, 2–4 prompt starters.
  4. Composer: Prompt input with the Model selector, and a disclaimer.
  5. 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} />
  • Map the SDK’s message parts to components: text → StreamingText, reasoning → Reasoning, tool calls → ToolCall, tool calls that need approval → Approval, source parts → Sources and InlineCitation.
  • Map its status to PromptInput status (submitted, streaming, ready, error) and its stop function to onStop.
  • Adapters for popular SDKs may ship later as optional packages; the components will not change.

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.

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.

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