Installation
pnpm dlx shadcn@latest add https://loading.design/r/smooth-stream.jsonUsage
import { SmoothStream } from "@/components/loading/smooth-stream"
<SmoothStream text={"Good things take a moment. Let’s make that moment better."} size={14} speed={0.35} active={true} />Pass the accumulated response as text and set active to false when the stream ends. Existing characters stay mounted while new characters fade in. This component displays plain text; render Markdown separately when needed.
With the AI SDK, read text from message parts and use the streaming status to control the cursor. See the AI SDK chat documentation.
import { useChat } from "@ai-sdk/react"import { SmoothStream } from "@/components/loading/smooth-stream"
export function ChatResponse() { const { messages, status } = useChat() const message = messages.at(-1) if (message?.role !== "assistant") return null const text = message.parts .filter(part => part.type === "text") .map(part => part.text) .join("") return <SmoothStream key={message.id} text={text} active={status === "streaming"} />}API
| Prop | Type | Default | Description |
|---|---|---|---|
| text | string | Good things take a moment. Let’s make that moment better. | Visible status copy or the accumulated streamed response. |
| size | number | 14 | Text size in pixels. |
| speed | number | 0.35 | Animation duration in seconds. For streaming text, this is the character fade duration. |
| active | boolean | true | Whether the animation is active. Disable when work finishes to hide the streaming cursor. |
| label | string | Streaming response | Accessible status label. Pass an empty string for decorative use. |
Accessibility
Streaming text uses a named region with aria-busy so every arriving character is not announced. Announce completion separately if needed. All patterns respect reduced motion; use an empty label for decorative output.