Skip to content
Mizen UI
Docs

IntroductionInstallationCLIStylingFoundationsThemingCompositionIntegrationsAccessibilityFor agents

useCopyToClipboard

AccordionAspect RatioCardCollapsibleFrameGridGroupInlineScroll AreaSectionSeparatorSpacerStack

BlockquoteCitationCodeHeadingKbdLabelLinkTextVisually Hidden

ButtonButton GroupToggleToggle groupToolbar

CalendarCheckboxCheckbox groupComboboxDate pickerDate range pickerDate-Time InputFieldFieldsetFile UploadFormInputInput groupNumber fieldOTP FieldRadio groupSelectSliderSwitchTextareaTime Input

BreadcrumbMenubarNavigation MenuPaginationSegmented ControlStepperTabs

Alert dialogCommandContext MenuDialogDrawerMenuPopoverPreview CardSheetTooltip

AlertBadgeEmptyError StateMeterProgressSkeletonSpinnerStatus dotToast

Activity FeedAvatarAvatar GroupData TableListMetricOverflow ListProperty ListTableTokenTree

Area ChartBar ListCalendar HeatmapCategory ComparisonChart FrameChart LegendChart TooltipDistributionFunnelHeatmapMetric TrendPart-to-WholeProgress RingsRadar ChartRadial BarsSankey ChartScatter ChartScore GaugeTime Series

Diagram

AttachmentCarouselCode BlockLightboxMarkdownThumbnailTimestamp

Agent ThinkingApproval CardComposerConversationInline CitationMessageMessage ScrollerQuestion CardSourcesStreaming TextSuggestionTask ListTerminalTool Call

On this page

  • Preview
  • Usage
  • With the AI SDK
  • With TanStack AI
  • Examples
  • Interrupted reply
  • Recommendations
  • Usage boundaries
  • API reference

Agentic

Streaming Text

Shows a reply as it streams: new words arrive in a fading color trail, citations sit inline, then actions, sources, and follow-ups appear.

idle

Usage

import { StreamingText } from "@mizen-labs/ui";

With the AI SDK

Join the text parts of the latest assistant message and pass useChat's status. source-url parts become linked sources and source-document parts show as titled text. If the provider writes [1] markers, they become chips for those sources. Earlier replies in the thread are complete; only the latest one streams.

import { useChat } from "@ai-sdk/react";
import { StreamingText, type StreamingTextSource } from "@mizen-labs/ui";

export function AssistantReply() {
	const { messages, regenerate, status } = useChat();
	const reply = messages.findLast((message) => message.role === "assistant");
	if (!reply) return null;
	const content = reply.parts
		.flatMap((part) => (part.type === "text" ? [part.text] : []))
		.join("");
	const sources: StreamingTextSource[] = reply.parts.flatMap((part) => {
		if (part.type === "source-url") return [{ href: part.url, title: part.title }];
		if (part.type === "source-document") return [{ title: part.title }];
		return [];
	});
	return (
		<StreamingText
			content={content}
			onRetry={() => regenerate()}
			sources={sources}
			status={
				status === "error"
					? "error"
					: status === "streaming" || status === "submitted"
						? "streaming"
						: "complete"
			}
		/>
	);
}

With TanStack AI

Text parts carry content rather than text, and reload() runs the last message again. Its message parts have no source type, so map cited pages from your search tool's results into sources.

import { fetchServerSentEvents, useChat } from "@tanstack/ai-react";
import { StreamingText } from "@mizen-labs/ui";

export function AssistantReply() {
	const { messages, reload, status } = useChat({
		connection: fetchServerSentEvents("/api/chat"),
	});
	const reply = messages.findLast((message) => message.role === "assistant");
	if (!reply) return null;
	const content = reply.parts
		.flatMap((part) => (part.type === "text" ? [part.content] : []))
		.join("");
	return (
		<StreamingText
			content={content}
			onRetry={reload}
			status={
				status === "error"
					? "error"
					: status === "streaming" || status === "submitted"
						? "streaming"
						: "complete"
			}
		/>
	);
}

Examples

Interrupted reply

When the stream fails, the partial reply stays with a stopped note, Copy, and Retry.

Recommendations

GuidancePractice
Do

Pass the reply so far on every update and set status to complete when the stream ends. Place each citation right after the claim it supports.

Usage boundaries

GuidanceBoundary
Scope

The application owns the stream, retries, and where feedback is stored. Streaming Text shows them; it does not fetch or send anything.

Scope

It renders plain text with inline citations. Use Markdown for formatted replies.

API reference

Public props from @mizen-labs/ui. Use exported prop types for the complete TypeScript contract.

PropTypeDefaultDescription
contentstring | readonly StreamingTextPart[]—The reply so far: a string, or text with { source } citations placed where the model cites. [n] markers in the text become citations of sources[n - 1]. Pass the growing value as it streams; only new words animate, and a burst staggers in.
status"streaming" | "complete" | "error"—streaming runs the color trail on new words and keeps the actions inert; error keeps the partial reply with a stopped note, Copy, and Retry; complete reveals actions, sources, and follow-ups. A reply mounted as complete does not animate.
sourcesreadonly StreamingTextSource[][]Cited sources. A link shows its domain and the site's favicon, and its title is optional. A source without href, such as an uploaded document, needs a title and shows as text.
onRetry / onFeedback() => void / (feedback) => void—Show Retry and Good / Bad response buttons. Copy is always available. Feedback is controlled by the feedback prop.
followUps / onFollowUpreadonly string[] / (prompt, index) => void[]Prompts offered once the reply is complete; onFollowUp receives the prompt and its index.
PreviousSourcesNextSuggestion

Container queries style an element by the size of its container, where media queries

The reply stopped before it finished.

The reply stopped before it finished.