AI Chat@paxeer/ai-chat/streaming-textimplemented
Streaming text
Token stream renderer with Skeleton while empty.
Install
$
pnpm exec designx add @paxeer/ai-chat/streaming-textPreview
Loading preview...
Source code
components/designx/ai-chat/streaming-text.tsxtsx
"use client";
import { useEffect, useState } from "react";
import { Badge, Skeleton } from "@paxeer/core";
export function StreamingText({
text = "Two working bids sit under 2479. Drafting 1.50 ETH at 2480.40 keeps you inside the current clip.",
streaming = true,
}: {
text?: string;
streaming?: boolean;
}) {
const [shown, setShown] = useState(streaming ? "" : text);
useEffect(() => {
if (!streaming) {
setShown(text);
return;
}
setShown("");
let index = 0;
const id = window.setInterval(() => {
index += 2;
setShown(text.slice(0, index));
if (index >= text.length) window.clearInterval(id);
}, 24);
return () => window.clearInterval(id);
}, [streaming, text]);
const done = shown.length >= text.length;
return (
<div data-slot="streaming-text" className="flex flex-col gap-2">
<Badge variant={done ? "secondary" : "default"}>{done ? "complete" : "streaming"}</Badge>
{shown.length === 0 ? (
<div className="flex flex-col gap-2">
<Skeleton className="h-4 w-5/6" />
<Skeleton className="h-4 w-2/3" />
</div>
) : (
<p className="text-[length:var(--md-sys-typescale-body-medium-size)] text-on-surface">
{shown}
{!done ? (
<span aria-hidden className="ml-0.5 animate-pulse text-primary">
▍
</span>
) : null}
</p>
)}
</div>
);
}
Dependencies
Registry dependencies