Skip to content
Kura UI

Reasoning

beta

Collapsible thinking trace: a shimmering “Thinking… 12s” label while active that settles into “Thought for 14s”, revealing muted reasoning text.

@kura-ui/react/reasoningCopy page for agents.mdregistry.json

Finished trace

minimal
Thought for 14s
The user wants the like button to feel instant. The lag comes from waiting on the server round-trip before re-rendering. Options: optimistic local state with manual rollback, or useOptimistic inside a transition. useOptimistic handles the rollback automatically if the action throws, and keeps the UI consistent with concurrent updates. I should recommend useOptimistic and show the minimal pattern, then mention the error case.

Live thinking that auto-collapses

Streams the trace with StreamingText while active (controlled open), then collapses to “Thought for Ns”.

full
Thinking

Above an assistant answer

Inside a Message, with a custom label.

composition
Kura
Kura
Thought for 1m 23s
The user wants the like button to feel instant. The lag comes from waiting on the server round-trip before re-rendering. Options: optimistic local state with manual rollback, or useOptimistic inside a transition. useOptimistic handles the rollback automatically if the action throws, and keeps the UI consistent with concurrent updates. I should recommend useOptimistic and show the minimal pattern, then mention the error case.

Use useOptimistic: render the new count immediately, then let React reconcile when the server action resolves. If it throws, the optimistic value is dropped for you.

Installation

npx shadcn@latest add https://kuro.abstergo.fyi/r/reasoning.json

Copies the source into components/kura/reasoning with its dependencies (kura-theme, shimmer-text, use-controllable-state, utils). Tokens come from the kura-theme item.

When to use it

Use it for

  • Show a reasoning model's chain of thought / thinking blocks (Claude extended thinking, o-series reasoning summaries) above the answer.
  • Indicate that the model is thinking, with elapsed time, before the first answer token arrives.
  • Keep a finished trace available but out of the way (collapsed to one line).

Reach for something else when

  • A bare “Thinking…” label with no trace to reveal — use shimmer-text (or thinking-indicator).
  • A sequence of discrete agent steps with states — use agent-timeline.
  • A single tool invocation with arguments and results — use tool-call.

Props

PropTypeDefaultDescription
activebooleanfalseThe model is still thinking: the label shimmers and an elapsed timer ticks. Turning it false settles the label and (with autoCollapse) collapses the trace.
durationnumber—Seconds spent thinking, if you know it (e.g. stored with the message). Otherwise measured while `active`.
openboolean—Expanded (controlled).
defaultOpenboolean—Initial expanded state when uncontrolled. Defaults to `active`: open while thinking, closed for finished traces.
onOpenChange(open: boolean) => void—Called when the trace is expanded/collapsed (by the reader or by auto-collapse).
autoCollapsebooleantrueCollapse when `active` turns false — skipped if the reader toggled it while it was active.
formatLabel(state: { active: boolean; seconds: number }) => React.ReactNode—Custom label (i18n, “Planning…”). Default “Thinking… 12s” / “Thought for 14s” / “Thought for a moment”.

All native attributes of the root element, className and ref pass through.

Anatomy

  1. ReasoningRoot. `data-status="active" | "done"`, `data-state="open" | "closed"`.data-slot="reasoning"
  2. TriggerButton with the label and a chevron that rotates 90° when open (aria-expanded, aria-controls).data-slot="reasoning-trigger"
  3. LabelShimmerText; shimmers while active, muted when done. Seconds are tabular.data-slot="reasoning-label"
  4. ContentMuted, pre-wrapped trace behind a left hairline. Animates grid-template-rows 0fr↔1fr (interruptible) and is inert when closed.data-slot="reasoning-content"

Accessibility

  • The trigger is a real button with aria-expanded/aria-controls.
  • A visually hidden status region says “Thinking” and then “Thought for 14s” — the ticking seconds are never announced.
  • When collapsed, the trace is `inert`: out of the tab order and the accessibility tree.
  • Reduced motion: The shimmer becomes static muted text, the chevron snaps, and the trace only fades (no height travel or blur).
KeysAction
Enter / SpaceExpand or collapse the trace

Notes for agents

  • Keep the component mounted from the first thinking token to the end; flip `active` instead of swapping components, so the timer and collapse work.
  • Persist the measured duration with the message and pass it as `duration` when re-rendering history.
  • Put a StreamingText (caret={false}) inside for a live trace; plain text or markdown for a stored one.