Streaming text & shimmer
StreamingText renders a reply as it arrives, with a gradient caret, and tells screen readers about finished sentences in batches instead of every token. Shimmer sweeps a soft light across short status lines. Both stop moving when the person prefers reduced motion.
Add the source to a shadcn project
npx shadcn@latest add https://docs.atomus.io/r/ai-streaming-text.jsonOpen in v0Installs the component source, its CSS and the Atomus tokens into components/atomus/. How the registry works
Shimmer
Section titled “Shimmer”In Figma
Section titled “In Figma”From guidelines/components/ai-streaming-text.md
Properties, variants and anatomy of the Figma components. React props use the same names.
Streaming text
Section titled “Streaming text”Renders an AI reply as it arrives: the text grows, a caret filled with --gradient-ai blinks at the end, and screen readers hear finished sentences in calm batches instead of every token. It takes any growing string, so it works with every AI SDK or backend. Part of the Agent kit.
Figma: component set Streaming text on the 🤖 Agent kit page of Atomus 4.0 (node 25544:55), connected to React with Code Connect. Status text: Shimmer (node 25544:34). React props use the same names as the Figma properties below.
| Property | Type / options |
|---|---|
| Text | text |
| State | Streaming · Done |
| Caret | boolean (on) |
| Announce | Polite · End · Off |
The caret blinks at --motion-stream-caret-blink (1s). Under prefers-reduced-motion: reduce it stays solid.
Use for
- The text of an assistant Message while it streams.
- Live summaries or drafts that an agent writes into a panel.
Not for
- Status lines such as “Thinking…”: use Shimmer.
- Text that arrives all at once: render it directly.
Accessibility
announce="polite"(default) puts finished sentences into a polite live region at most everyannounceIntervalms (1500), then the rest when the stream ends, then clears the region.announce="end"only saysdoneMessage(“Response complete”); use it for long code or tables.announce="off"when an outer region already announces.- The visible text has
aria-busywhile streaming, so assistive tech doesn’t read half words.
Shimmer
Section titled “Shimmer”A light sweep across short status text while the agent works (“Thinking…”, “Searching 12 sources…”). The sweep runs through text-ai over text-tertiary every --motion-stream-shimmer-duration (1.8s); reduced motion shows static text-tertiary text.
| Property | Type / options |
|---|---|
| Label | text |
| Animated | boolean (on) |
import { StreamingText, Shimmer } from '@stanvision/atomus-react';
// Pass the whole string received so far on every chunk.<StreamingText text={text} streaming={!done} render={(t) => <Markdown>{t}</Markdown>} />
// Long code or tables: only say when it's done.<StreamingText text={code} streaming={!done} announce="end" doneMessage="Code ready" />
<Shimmer>Searching 12 sources…</Shimmer>Motion tokens
Section titled “Motion tokens”--motion-stream-caret-blink(1s) and--motion-stream-shimmer-duration(1.8s). Both become0sunderprefers-reduced-motion: reduce, and the components switch their animation off.
Design guidance
Section titled “Design guidance”From the Figma guidelines.
Streaming text
Section titled “Streaming text”Do
- Pass the whole string received so far on every chunk.
- Use
renderfor Markdown or to turn citation markers into InlineCitation. - Use
announce="end"for code, tables and very long answers.
Forbidden
- Never announce every token or chunk to screen readers.
- Never animate the caret when the person prefers reduced motion.
- Never move focus to the streaming text.
Shimmer
Section titled “Shimmer”Do
- Keep the label short, in sentence case, ending with an ellipsis.
- Swap the shimmer for a static result as soon as the step ends (“Thought for 12s”).
Forbidden
- Never shimmer body text, buttons or links.
- Never use Shimmer as the only signal of progress for a long task — show steps or a Progress bar.
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-streaming-text.md.
Use only these props; anything else is not part of the API.
StreamingText
Section titled “StreamingText”Figma: Streaming text — renders an AI reply as it arrives, with a caret and batched, polite screen-reader announcements. Framework-agnostic: feed it any growing string.
import { StreamingText } from '@stanvision/atomus-react'; — source: react/src/components/ai/StreamingText.tsx
| Prop | Type | Default | Description |
|---|---|---|---|
text |
string |
required | The text received so far. Pass the growing string on every chunk; the component only appends. |
streaming |
boolean |
false |
Figma: State=Streaming — shows the caret and keeps the region busy for screen readers. |
caret |
boolean |
true |
Figma: Caret — blinking caret at the end while streaming (static under reduced motion). |
announce |
'polite' | 'end' | 'off' |
'polite' |
How screen readers hear the stream (Primer: announce progress, not every token). polite (default) — finished sentences in batches, at most every announceInterval ms. end — only doneMessage once the stream ends. off — nothing; use when an outer live region already announces the reply. |
announceInterval |
number |
1500 |
Minimum time between announcements in ms |
doneMessage |
string |
'Response complete' |
Announced when the stream ends with announce="end" |
render |
(text: string) => ReactNode |
— | Renders the text (e.g. Markdown). Defaults to plain text with preserved line breaks. |
Also accepts every native <div> attribute (id, role, onClick …), except children, which is replaced above.
Shimmer
Section titled “Shimmer”Figma: Shimmer — a light sweep across status text while the agent works. The sweep uses –gradient-ai and –motion-stream-shimmer-duration; reduced motion shows static text.
import { Shimmer } from '@stanvision/atomus-react'; — source: react/src/components/ai/StreamingText.tsx
| Prop | Type | Default | Description |
|---|---|---|---|
children |
ReactNode |
required | Figma: Label — short status text such as “Thinking…” or “Searching the web…” |
active |
boolean |
true |
Figma: Animated — when false the text renders static (as under reduced motion). |
Also accepts every native <span> attribute (id, title …).