Reasoning & Streaming

Two small primitives convey that a turn is still in progress: <Reasoning> folds
the model’s thinking into a dim, collapsible block, and <StreamingText> shows a
blinking caret while tokens arrive.
Reasoning
Section titled “Reasoning”A collapsible “thinking” block: a dim ✻ header with a live spinner while
active, and the (streaming) reasoning text below — secondary chrome that folds
away. It expands while active and can collapse itself when reasoning finishes,
leaving a "thought for 3s" line.
import { Reasoning, Markdown } from "@huyz0/ztui/react";
<Reasoning active={thinking} duration={thinking ? undefined : "thought for 3s"} collapseWhenDone> <Markdown trimTrailingMargin>{reasoningText}</Markdown></Reasoning>;label— header text (defaults to"Thinking").active— while true, shows the spinner and stays expanded.duration— dim line shown once done.collapseWhenDone— auto-collapse whenactiveturns false.open+onToggle(controlled) ordefaultOpen(uncontrolled, defaults to whether it starts active). The body stays mounted while collapsed, so streamed text keeps accruing behind it.
StreamingText
Section titled “StreamingText”Inline text with a blinking caret while it streams — the token-by-token
“typing” affordance. Pass the accumulated text and flip streaming to false
when the turn completes; the caret then disappears. It animates itself off the
render clock (no ticking prop), and word-wraps long replies to the bubble width.
import { StreamingText } from "@huyz0/ztui/react";
<StreamingText streaming={!done}>{reply}</StreamingText>;streaming— whether to show the caret.caret— caret glyph (defaults to▋).blinkMs— blink period.
For rich replies, render Markdown for the committed
text and use StreamingText only for the live tail.