Skip to content

LiveThinkingPanel

Hero example

When to use

Use LiveThinkingPanel anywhere the assistant streams thinking steps as it works — the /assistant chat, live agent traces, the playground post-stream replay. The panel is intent-first; steps should be emitted before the work starts, not after it completes, so the trail mirrors live intent.

Do — emit one think({ label }) event before each tool call so the trail mirrors live intent.
Don't — backfill the trail from completed tool calls; that turns thinking into a log and loses the live texture.

Anatomy

The panel is a thin recipe over ThinkingTree in carded mode:

  1. Header. Always present. Reads Thinking · step N of M while live, Thought for {duration} · {n} steps once final.
  2. Body. A vertical <ol> of rows mirroring the ThinkingTree anatomy — hairline rail, dot, label. The active row carries the glass pill + moving-gradient shimmer.
  3. Empty-live placeholder. When state === "live" and no steps have been emitted yet, a single Thinking… placeholder row keeps the surface non-empty.

The panel is anchored to the left by MatterMarkAvatar in the recommended assistant-row recipe.

Props

PropTypeDefaultDescription
stepsrequiredLiveThinkingStep[]
staterequiredLiveThinkingPanelState
elapsedMsrequirednumberTotal elapsed time for the turn, in milliseconds.
onStepRevealed(id: string) => voidLegacy hook for when a step's reveal animation completes. The v2 surface no longer needs this signal (the chat-panel reducer already promotes the previous step on every new `think` event), but the prop is kept for back-compat. Calls are silently ignored.
defaultOpenbooleanOverride the default open state. Defaults: live → open, final → closed.
classNamestring
aria-labelstring

onStepRevealed is a legacy hook from the previous word-reveal animation; it remains in the type signature for back-compat but is a no-op in the v2 surface. The chat-panel reducer already promotes the previous step to done on every new think event.

States

Variants

state is the primary axis:

  • live — body open, header reads Thinking · step N of M, the latest step typing.
  • final — body collapsed by default, header reads Thought for X · N steps. Click the header to re-expand.

The body's open/closed state can be overridden with defaultOpen.

Density

Themes

Tokens consumed

No tokens match.

Inherits all ThinkingTree tokens — --status-green, --status-red, --fg, --fg-muted, --fg-soft, --ink-8/15, --paper-72/85/90, --bg, --hairline, --focus-ring. No new tokens introduced.

Accessibility

  • Header is a real <button> with aria-expanded + aria-controls.
  • Group landmark via role="group" + aria-label.
  • Active row carries aria-current="step".
  • prefers-reduced-motion honoured by the underlying ThinkingTree.

Recipes

Assistant chat row

Mount the MatterMarkAvatar on the left, the panel on the right:

import { LiveThinkingPanel, MatterMarkAvatar } from "@matter/components";

export function AssistantRow({ steps, elapsedMs, state }) {
  return (
    <div className="flex items-start gap-3">
      <MatterMarkAvatar />
      <div className="min-w-0 flex-1">
        <LiveThinkingPanel
          elapsedMs={elapsedMs}
          state={state}
          steps={steps}
        />
      </div>
    </div>
  );
}

The avatar persists left of the collapsed-summary once state transitions to "final", so the avatar + header pair anchors each turn in the scrollback.

Source

packages/components/src/ThinkingTree/LiveThinkingPanel

On this page