Skip to content
hightouchUI

Design system

c6c48ee

Agent activity

Agent activity is a streaming log of what an AI agent is doing — reasoning text, steps, web searches, tool calls, or a full execution trace — shown in a capped viewport while the run works, then collapsed behind a summary disclosure when it completes.

Use Spinner when you only need to signal loading with no per-event detail.

Example

The log is collapsed to its shimmering status row by default — the demos on this page open it so you can watch the run. Reasoning text streams into a viewport that grows to maxViewportHeight, then glides upward so the newest tokens stay visible. This demo caps the viewport well below the default 208px so the glide is visible in a short run. On completion the log collapses into a "Thought for …" disclosure.

useAgentActivityDemo and ReplayDemoButton are docs-only scaffolding, not library exports — in product code, append to items and flip status as your agent's events stream in. Their source is docs/components/demos/.

Usage

Step

step items render a checklist with pending, active, and complete states, plus an optional trailing meta. The completed summary derives from the run duration.

search items show a query with results revealing as they arrive, plus an optional moreCount overflow line. Results with a url render as links.

Tool

tool items pair an action verb with a monospace target; edit-style actions can carry additions and deletions line counts.

Trace

trace items interleave thinking, messages, and tool events in one chronological run — the densest view, closest to a raw agent log. The kind picks the icon; pass icon to override it.

Mixed

A run that chains item types renders each with its own row treatment; the viewport glides upward as the log outgrows maxViewportHeight. The summary falls back to a completed step count.

Before the first item

Until the first item arrives there is nothing to disclose, so items can be left off entirely and the run renders as a plain shimmering line: no chevron, no disclosure, and nothing for the keyboard to land on. contentType picks the label — "Thinking…" for steps — and activeLabel overrides it. Use this state for an agent that is still deciding whether to act.

Sizes

Two sizes, defaulting to md. Only the status row scales — rows render at sm in both, so size="sm" reads as one uniform block rather than a headline over smaller detail. Use it on dense surfaces like a comment thread.

Collapsed while working

Collapsed is the default posture: a working run is one line that takes no vertical space, suiting dense surfaces like a comment thread. The shimmering label is the run's newest activity, rolling up as it changes; reasoning text items are the exception and keep the generic "Thinking…" (a paragraph is too long for a headline). Pass activeLabel to override the label. The row is a disclosure — while a run is collapsed and working the chevron stays hidden until you hover or focus the row, and clicking reveals the live log mid-run. Every other posture shows it outright.

Collapse on complete

The disclosure is available throughout the run: defaultIsOpen and isOpen + onOpenChange set or control it at any point. When status flips to complete, an open log collapses behind its summary unless collapseOnComplete={false}. This example starts completed — click the summary to expand it.

Custom status

activeLabel and summary replace the derived strings when text is all you need.

Custom status contents

renderWorkingStatus and renderCompletedStatus replace the whole status row when it needs more than a string — a badge, a count, an icon. The completed row still gets the disclosure chevron after whatever you return.

Guidelines

When to use

  • To show what an agent is doing while it works — reasoning, steps, searches, tool calls, or a full trace — and keep the finished log reviewable behind a summary
  • When events stream in over time: the log grows to maxViewportHeight, then glides upward so the page stops reflowing
  • A capped log auto-follows the newest row while it works — earlier rows stay out of reach until the run completes, and the viewport scrolls from then on
  • Collapsed is the default posture — the status row shimmers with the run's newest activity; pass defaultIsOpen on chat-style surfaces where the log should stream in the open

When not to use

  • For a plain loading state with no per-event detail — use Spinner or Skeleton
  • For static checklists or setup progress that isn't an agent run — compose Column, Row, and Text
  • For long-form logs users need to copy or search — use CodeSnippet

Content

  • Keep item labels short and scannable — sentence case, no trailing punctuation
  • Active labels are present tense with a trailing ellipsis ("Searching the web…"); summaries are past tense ("Searched the web")
  • Put paths, commands, and queries in target / detail so they render in the monospace chip

Accessibility

  • Once there are items, the status row is one persistent button (aria-expanded, aria-controls) across both phases, so keyboard focus survives the working-to-complete swap; an empty run is a static line, with nothing for the keyboard to land on. Phase changes announce through a visually hidden polite live region with stable text, so the streaming headline never chatters through a screen reader
  • The log is marked aria-busy while working; when collapsed it is hidden from the accessibility tree and leaves the tab order
  • The shimmer, pulse, and glide animations all honor prefers-reduced-motion

Props

Inherits margin props.

AgentActivity

NameDefaultDescription
items

AgentActivityItem[]Chronological activity entries. Append or update items as events stream. Optional, because a run that has not reported anything yet is a real state: the status row renders alone, with no disclosure behind it.
contentType

AgentActivityContentTypeExpected activity kind before the first streamed item arrives.
size"md""sm" | "md"Scales the status row. Rows always render at sm, so size="sm" flattens the run into one uniform block for dense surfaces like a comment thread.
status"working"AgentActivityStatusCurrent run phase.
duration0numberElapsed run time, in seconds. When greater than zero, the step and text summaries read "Thought for …"; otherwise they fall back to "Finished thinking".
isOpen

booleanControlled expanded state.
defaultIsOpenfalsebooleanInitial expanded state, when isOpen is not controlled. Pass true on surfaces that should stream the log in the open.
onOpenChange

(open: boolean) => voidCalled when the disclosure opens or closes.
collapseOnCompletetruebooleanCollapse the disclosure when status changes from working to complete.
activeLabel

ReactNodeOverrides the label shown while the run is active — including the newest-activity headline a collapsed run derives from its items.
summary

ReactNodeOverrides the completed summary. Derived from the item types by default.
renderWorkingStatus

(context: { label: ReactNode }) => ReactNodeOverrides the contents of the active status row.
renderCompletedStatus

(context: { summary: ReactNode }) => ReactNodeOverrides the contents before the built-in disclosure chevron.
maxViewportHeight208numberMaximum visible activity height, in pixels, before the stream begins gliding.