Streaming Text
Words resolve into a paragraph one at a time, through a small blur.
Installation
npx shadcn@latest add @loomui/streaming-textUsage
import { StreamingText } from "@/components/ui/streaming-text"<StreamingText active={isStreaming} text="The full paragraph, all at once." />How it works
The text is split into words up front rather than typed character by
character — every word is already in the DOM, resting at opacity: 0 and
blurred. Turning active on doesn't fade them all in together: each word's
data-in attribute flips on its own setTimeout, staggered by wordGap, so
the paragraph resolves left to right the way a response actually streams in.
Replaying is the same trick ThinkingText uses for its state swap: wipe
every word back to hidden with data-resetting (which forces transition: none), let two animation frames pass so the browser commits that as a real
paint rather than getting collapsed into the next update, then release the
reset and start staggering data-in back on. Without that forced frame, the
"hidden" state and the first reveal would land in the same paint and nothing
would visibly reset.
Replaying on purpose
Toggling active off and back on replays the whole paragraph from scratch —
that's deliberate, not a bug. If text changes while active is already
true, it replays too. For streamed content, wait for the full string before
mounting with active, or swap in the whole component with a key change
when you want a clean rerun, the way the demo does it.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
active | boolean | false | Runs the reveal. Off shows the text at once. |
text | string | - | The full paragraph, split on whitespace. |
wordGap | number | 45 | Milliseconds between each word's reveal. |
fadeDuration | number | 320 | Milliseconds each word's fade-in takes. |
className | string | - | Merged onto the wrapper. |
Any other <span> prop is forwarded.
Reduced motion
Every word renders at full opacity with no blur and no transition — the paragraph is just there, in one paint, with nothing to stagger through.