Streaming

Render AI responses progressively to create a real-time experience. Supports character, word, or staged transitions for natural output flow.

Preview

import { Streaming } from "@/registry/streaming";

const SAMPLE =
  "Stream text by character, word, or fade — optional typewriter bar on any mode.";

export function StreamingDemo() {
  return (
    <div className="max-w-xl text-left text-sm leading-relaxed text-foreground">
      <Streaming
        variant="characters"
        text={SAMPLE}
        speedMs={24}
        showCursor={false}
      />
    </div>
  );
}

Installation

pnpm dlx @arrowui/cli@latest add streaming

Usage

import { Streaming } from "@/registry/streaming";
<Streaming variant="characters" text={text} speedMs={24} showCursor />

Examples

Characters

Reveals the string one character at a time. Best for typewriter or token-level streaming UX.

import { Streaming } from "@/registry/streaming";

const SAMPLE =
  "The characters variant reveals one code point at a time. Whitespace is preserved; combine with showCursor for a classic typewriter look.";

export function StreamingCharactersDemo() {
  return (
    <div className="max-w-xl text-left text-sm leading-relaxed text-foreground">
      <Streaming variant="characters" text={SAMPLE} speedMs={20} />
    </div>
  );
}

Words

Splits with /(\s+)/ so spaces stay attached to the right tokens — each step adds the next segment.

import { Streaming } from "@/registry/streaming";

const SAMPLE =
  "Words splits on whitespace and keeps spaces between tokens. Each step appends the next segment — good for chat-style lines without per-letter cost.";

export function StreamingWordsDemo() {
  return (
    <div className="max-w-xl text-left text-sm leading-relaxed text-foreground">
      <Streaming variant="words" text={SAMPLE} speedMs={70} />
    </div>
  );
}

Fade

Each segment uses Motion to fade from transparent with blur to full opacity — tuned for a soft, readable entrance.

import { Streaming } from "@/registry/streaming";

const SAMPLE =
  "Fade animates each segment from transparent with a light blur into fully sharp text. Default pacing is a bit slower so each fade can read before the next chunk.";

export function StreamingFadeDemo() {
  return (
    <div className="max-w-xl text-left text-sm leading-relaxed text-foreground">
      <Streaming variant="fade" text={SAMPLE} speedMs={130} />
    </div>
  );
}

Typewriter bar

Set showCursor to show the pulsing caret at the end while text is still streaming. Works for all three variants and hides when the stream finishes.

showCursor (default)

showCursor false

import { Streaming } from "@/registry/streaming";

const SAMPLE =
  "The same passage with and without the pulsing bar. Use showCursor on characters, words, or fade.";

export function StreamingCursorDemo() {
  return (
    <div className="flex flex-col gap-8 text-left text-sm leading-relaxed text-foreground md:flex-row md:gap-12">
      <div className="max-w-[min(100%,18rem)] space-y-2">
        <p className="text-xs font-medium tracking-wide text-muted-foreground uppercase">
          showCursor (default)
        </p>
        <Streaming variant="words" text={SAMPLE} speedMs={64} showCursor />
      </div>
      <div className="max-w-[min(100%,18rem)] space-y-2">
        <p className="text-xs font-medium tracking-wide text-muted-foreground uppercase">
          showCursor false
        </p>
        <Streaming
          variant="words"
          text={SAMPLE}
          speedMs={64}
          showCursor={false}
        />
      </div>
    </div>
  );
}

Props

PropTypeDefault
textstring
variant"characters" | "words" | "fade""characters"
speedMsnumber (delay between steps)22 · 78 · 130 by variant
showCursorboolean (typewriter while streaming)true
classNamestring
…spanOther span props