text
Streaming Text
Token-by-token reveal with a blinking cursor, interruptible mid-stream.
- text
- streaming
- chat
- typewriter
- cursor
Live preview
Here's a streamed response, arriving one token at a time.
Quick usage
usage
import { StreamingText } from "@pinky-ui/ai-ui";
<StreamingText text={partialResponse} streaming={isStreaming} />Presets
Default
A natural token-arrival pace.
Default behaviour
Fast
For long responses where the reveal shouldn't outlast reading.
speed={90}
Deliberate
A slower, more legible pace for short, important messages.
speed={24}
Install
Add @pinky-ui/ai-ui as a dependency, or use the CLI to copy this component's source directly into your project — no dependency to manage, fully editable.
shell
npm install @pinky-ui/ai-uishell
pnpm add @pinky-ui/ai-uishell
yarn add @pinky-ui/ai-uishell — copies source into your project
npx pinky-ui add streaming-textPrefer to run the whole repository locally instead?
repository
git clone https://github.com/florash/Pinky-UI.git
cd Pinky-UI
npm install
npm run devProps
| Prop | Type | Default | Description |
|---|---|---|---|
| text | string | — | The text revealed so far — grow it as tokens arrive to stream in real time. |
| speed | number | 45 | Characters revealed per second while animating. |
| streaming | boolean | true | Set to false to reveal the remaining text immediately, e.g. from a Stop button. |
| onDone | () => void | — | Called once the visible text catches up with `text`. |
| cursor | boolean | true | Shows a blinking block cursor while text is still catching up. |
| as | "p" | "span" | "div" | "p" | Element the text renders as. |
| className | string | — | Applied to the outer element. |
Accessibility
- The complete text is available to screen readers immediately through a visually hidden node — nobody has to wait on the animation to hear the message.
- The animated glyphs and blinking cursor are `aria-hidden`; only the hidden complete text is announced.
Performance
- Reveal runs off a single requestAnimationFrame loop per instance and cancels on unmount or when `text` changes to an unrelated value.
Reduced motion
With prefers-reduced-motion: reduce, the full text renders immediately and the cursor never appears.
When to use
- Assistant responses arriving over a stream (SSE, WebSocket, chunked fetch).
- Any place a typewriter reveal signals "still arriving" without blocking on it.
When not to use
- Static text that never streams — render it directly instead.
- Long-form content where a reveal would just delay reading.