Skip to content

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.

Streaming…
StreamingText with InlineCitation chips rendered from [n] markersLive · light and dark follow the theme switch

Add the source to a shadcn project

npx shadcn@latest add https://docs.atomus.io/r/ai-streaming-text.jsonOpen in v0

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

Thinking…Searching 12 sources…Writing the summary…Static (reduced motion)
Shimmer · active={false} renders static textLive · light and dark follow the theme switch

From guidelines/components/ai-streaming-text.md

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

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 every announceInterval ms (1500), then the rest when the stream ends, then clears the region.
  • announce="end" only says doneMessage (“Response complete”); use it for long code or tables.
  • announce="off" when an outer region already announces.
  • The visible text has aria-busy while streaming, so assistive tech doesn’t read half words.

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-stream-caret-blink (1s) and --motion-stream-shimmer-duration (1.8s). Both become 0s under prefers-reduced-motion: reduce, and the components switch their animation off.

From the Figma guidelines.

Do

  • Pass the whole string received so far on every chunk.
  • Use render for 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.

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.

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.

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.

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 …).