Streaming
Renders cumulative agent Markdown at a smooth, evenly paced reveal with a subtle animation for new content.
Fade In
Fades newly arrived characters into place.
Blur In
Sharpens newly arrived characters from a soft blur.
Slide Up
Moves newly arrived characters upward into place.
Slide Left
Moves newly arrived characters left into place.
Fold In
Unfolds newly arrived characters from a top hinge in 3D.
Streaming renders an AI response the way modern chat apps do: cumulative Markdown revealed at a smooth, even pace, with a subtle animation on newly arrived text. It is a React component for LLM chat interfaces — hand it the growing string from your model stream and it handles pacing, Markdown, and motion, in shadcn/ui and Tailwind CSS projects.
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
children | string | — | Provides the complete Markdown accumulated for the current response. |
isStreaming | boolean | false | Enables animation for content arriving during the active response. |
animation | "fadeIn" | "blurIn" | "slideUp" | "slideLeft" | "foldIn" | (string & {}) | "fadeIn" | Selects a supplied animation, or the name of one you add yourself. |
animationDuration | number | 400 | Sets the Streamdown duration and the final animation linger window, in milliseconds. |
Streaming also accepts standard div props except children. Those props
apply to the public root; Streamdown remains an internal Markdown renderer.
Behavior
Pass the complete response received so far on every render. Network chunks
arrive in uneven bursts, so Streaming buffers each update and reveals it a
few characters per frame at a rate proportional to the backlog: the display
trails the newest arrival by roughly a third of a second, speeds up when
chunks race ahead, and quickly drains what remains once isStreaming turns
false. Supplied animations use 400ms by default; custom effects can coordinate
their CSS duration and final linger window through animationDuration. This
pacing is the component's only behavior — there is no unsmoothed mode.
Fold In follows the same 400ms duration and adaptive reveal pacing as the
other built-in variants. It unfolds each newly arrived character from a top
hinge through a 700px perspective, then settles it into the normal text.
Text is revealed on grapheme boundaries, so CJK text, emoji, and combining marks never split mid-character. While the response grows, incomplete Markdown remains renderable and CJK punctuation works with emphasis and automatic links. Content already present when the component mounts renders immediately; pacing applies only to what arrives afterwards.
Reduced-motion preferences disable both the pacing and the animation, so content renders as soon as it arrives. When streaming ends and the reveal settles, the animation transformer is removed and the completed response renders without character-level animation spans.
The component intentionally does not manage messages, requests, retries, scrolling, persistence, code highlighting, math, or diagrams.
The public root defaults to dir="auto" and reflects the active response
through aria-busy, which stays true until buffered content finishes
revealing. The surrounding transcript owns announcements and controls such
as Stop, Retry, and Copy.
Tailwind setup
Streamdown's preset typography is distributed from its package. Keep these sources in the Tailwind CSS entry file, adjusting the relative path when the file is nested differently:
@source "../node_modules/streamdown/dist/*.js";
@source "../node_modules/@streamdown/cjk/dist/*.js";Do not also import streamdown/styles.css. Streaming installs its own
animation CSS. Its Slide Up and Slide Left variants move inline tokens with
relative offsets because transforms do not apply to inline boxes. Fold In
temporarily makes arriving characters inline-block so its 3D transform can
render. In particular, sd-slideUp intentionally differs from Streamdown's
transform-based version.
Add an animation
Each animation is one self-contained block of installed CSS: a @keyframes
rule and the mapping that selects it. Add the same pair for a name of your
own, then pass that name to animation. The prop type accepts any string, so
this needs no change to the component:
@keyframes sd-wipeIn {
from {
opacity: 0;
clip-path: inset(0 100% 0 0);
}
to {
opacity: 1;
clip-path: inset(0 0 0 0);
}
}
[data-slot="streaming"][data-sd-animation="wipeIn"] [data-sd-animate] {
animation-name: sd-wipeIn;
}Animate properties that apply to inline elements. opacity, filter,
clip-path, color, and relative offsets work; transform is ignored unless
you also make the token a block box, which changes where lines break.
Credits
The concise text-animation API is informed by Magic UI Text Animate. The cumulative Markdown contract follows the approach used by AI Elements Message and Streamdown Animation. The smooth pacing addresses the same problem as the AI SDK's smoothStream transform, but on the client, so it works with any transport. This component exposes an independent Vivid Layer API and does not depend on AI Elements or the AI SDK. Fold In adapts the top-hinged 3D motion language of React Bits Fold Text without adding GSAP or ScrollTrigger.