Streaming Text
A generating-text effect where characters settle in one by one with a soft blur, fade, or wave and a blinking caret while the response is still being written.
How it works
Each newly revealed character enters with a short micro-interaction chosen by effect: blur, fade, slide, or a spring wave. The reveal speed, delay, glyph timing, and caret behavior are configurable, and the whole stream can loop or call onComplete.
Accessibility
The animated characters are hidden from assistive technology while an sr-only copy of the full string sits in a polite status region, so screen readers hear the message once instead of every keystroke. Reduced-motion preferences render the finished string immediately.
Limitations
It animates plain strings only, so pass a single text value rather than rich markup. The visible text streams at a steady character rate; use a real streaming source for token-level timing.
Features
- Streams a string character by character at a configurable speed.
- Choose how each character settles: blur, fade, slide, or a spring wave.
- Optional blinking caret, with an option to keep it after the string ends.
- Tune blur amount, rise distance, and per-character duration.
- Delay the start and optionally loop the stream between cycles.
- Fire onComplete when the full string has been revealed.
- Groups characters by word so long responses still wrap correctly.
- Announces the finished message once and respects reduced motion.
Installation
Choose the CLI command or install the component manually.
$ npx @istmx/ui add streaming-textCopies the install command for your selected package manager.
Dependencies
Usage
Import the component from the file you copied it to, then use it like any other React component.
import StreamingText from '@/components/ui/streaming-text' <StreamingText text="Streaming means the answer arrives while it is written." /> <StreamingText text={answer} speed={46} effect="blur" startDelay={200} onComplete={() => setDone(true)}/> <StreamingText text="Thinking out loud…" effect="wave" glyphDuration={0.5} cursorAfterComplete loop/>Composition
StreamingText├── Animated glyphs├── Blinking caret└── Screen-reader textAPI reference
textstringThe string to reveal as if it is still being written.
speed?numberCharacters revealed per second. Defaults to 34.
startDelay?numberDelay in milliseconds before streaming begins. Defaults to 0.
effect?'fade' | 'blur' | 'slide' | 'wave'How each new character enters. Defaults to blur.
glyphDuration?numberSeconds for a single character to settle. Defaults to 0.34.
blurAmount?numberBlur radius in pixels used by the blur effect. Defaults to 6.
slideDistance?numberRise distance in pixels used by the slide, blur, and wave effects. Defaults to 6.
cursor?booleanShows the blinking caret while streaming. Defaults to true.
cursorAfterComplete?booleanKeeps the caret blinking after the string finishes. Defaults to false.
loop?booleanRestarts the stream after the string finishes. Defaults to false.
loopDelay?numberPause in milliseconds between loop cycles. Defaults to 1200.
onComplete?() => voidCalled once the full string has been revealed.
className?stringAdditional classes for the outer wrapper.
textClassName?stringClasses applied to the animated text.
cursorClassName?stringClasses applied to the caret.
The listed props match the current component implementation.
Data attributes
Streaming Text does not expose custom data attributes.
Examples
Feed StreamingText the same string your model returns and let it animate the arrival. It is display-only, so keep the real text in state and pass it in; the component never mutates your data.
Credits & inspiration
Created by Aryan (istmX) for ISTMX. The source-first, copy-and-own philosophy is inspired by shadcn/ui. About the creator