Components

Trace

The building block for reasoning, tool calls, sources and more.

Credits

Shout out to Shadcn Vue for the original Trace. This version adds more states, sizes, icon and chevron options, and renders any element through as / as-child.

Source code

Click to see the source code for this component on GitHub. Feel free to copy it and adjust it for your own use.

Installation

Trace uses the shimmer utility for the running state. If you have not added it yet, follow the steps in Shimmer.

About

Trace is a list of lines. Each line has an icon, a title, and an optional description and status. A line can expand to show more detail, link to a page, or open a dialog or sheet.

Every line has the same shape, so reasoning, tool calls, sources and plans built from Trace look and behave the same. Use Trace for the steps an agent takes, like calling a tool, running a subagent or editing a file. Use Message for its reply, and Marker for notes and dividers between turns.

Why does pnpm install fail in CI?
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

The last commit bumped a version in package.json without updating pnpm-lock.yaml, so the frozen install fails. Run pnpm install locally and commit the lockfile.

Built with Trace

Every pattern below is a composition of Trace parts. See AI Elements for examples and code.

PatternShows
Chain of ThoughtA summary that expands into the steps behind it.
PlanThe steps the agent plans to take, and how far it has got.
QueueThe agent's todo list, split into what is left and what is done.
ReasoningThe agent's thinking as it streams.
SourcesThe links the agent used for a reply.
Stack TraceA failed tool call and its stack frames.
SubagentA subagent run, with its tool calls and result.
TaskThe steps the agent takes, as it takes them.
TerminalA command the agent runs, with its output as it streams.
Test ResultsA test run by the agent, with its suites and failures.
ToolA tool call the agent makes, from input to output.

Usage

Use a UiTraceLine for a single step:

<template>
  <UiTrace>
    <UiTraceLine>
      <UiTraceIcon name="lucide:search" />
      <UiTraceTitle>Searched for minimumReleaseAge</UiTraceTitle>
    </UiTraceLine>
  </UiTrace>
</template>

Wrap the line in a UiTraceCollapsible to show more detail when it expands:

<template>
  <UiTrace>
    <UiTraceCollapsible>
      <UiTraceCollapsibleTrigger>
        <UiTraceLine>
          <UiTraceIcon name="lucide:terminal" />
          <UiTraceTitle>Ran node --version</UiTraceTitle>
        </UiTraceLine>
      </UiTraceCollapsibleTrigger>
      <UiTraceCollapsibleContent>v24.18.0</UiTraceCollapsibleContent>
    </UiTraceCollapsible>
  </UiTrace>
</template>

Composition

Use the following composition to build a trace line:

UiTrace
└── UiTraceLine
    ├── UiTraceIcon
    ├── UiTraceTitle
    ├── UiTraceDescription
    └── UiTraceIcon

Wrap the line in a UiTraceCollapsible to show more detail when it expands:

UiTrace
└── UiTraceCollapsible
    ├── UiTraceCollapsibleTrigger
    │   └── UiTraceLine
    └── UiTraceCollapsibleContent

UiTraceLine is always the line. To make a line do something, wrap it in that thing's trigger.

Features

  • One row for reasoning, tool calls, sources, plans and tasks
  • Rows that expand, link out, or open a dialog, sheet, drawer or popover
  • running, error, pending, success and warning states, with a shimmer while running
  • Two sizes, default and sm
  • Icons by name (<UiTraceIcon name="lucide:search" />) or with your own markup
  • A chevron you can hide, swap for another icon, or replace through a slot
  • Nested rows, so a summary expands into steps and a step into its output
  • Every part renders any element through as and as-child
  • Works with reasoning, tool and source parts from the AI SDK
  • Keyboard and screen reader support from the trigger that wraps each row
  • Customizable styling through the class prop on every part

Trace Line

Use a UiTraceLine on its own for a step with no detail to show. It reads as plain text.

Created branch fix/frozen-lockfile

Status

Set status on UiTraceLine when a step is running, has failed or hasn't started yet.

Ran pnpm installFailed to run pnpm lintRunning pnpm buildRun pnpm test
StatusUse for
noneWork that is done: "Ran pnpm install".
"success"Work that finished and you want to say so, in green.
"warning"Work that finished with something to look at, in amber.
"error"Work that failed. Say so in the title: "Failed to run pnpm lint".
"running"Work in progress. Write the title in the present tense: "Running pnpm build".
"pending"Work that has not started, such as a plan step: "Run pnpm test".

Size

Use size="sm" for denser lists such as a long plan or a queue. The icon scales with the line.

Searched for minimumReleaseAgedefaultRan pnpm install
Searched for minimumReleaseAgesmRan pnpm lint with 2 warnings

Description

Put secondary text such as a diff stat, a duration or a count in a UiTraceDescription after the UiTraceTitle. It does not truncate.

Edited components/settings/NotificationPreferencesForm.vue +48 −12 Ran pnpm test14sSearched for useChat8 results

Collapsible

Wrap the line in a UiTraceCollapsible to show more detail when it expands. Put the UiTraceLine inside UiTraceCollapsibleTrigger and the detail in UiTraceCollapsibleContent.

Chevron

The trigger adds a chevron after the line. Hide it with :chevron="false", pick another icon with chevron-icon, or replace it through the chevron slot. Set :bordered="false" on the content to drop the rule and indent on its left.

Open State

Rows start closed. Use default-open on UiTraceCollapsible to start open, or v-model:open to control a row. The default slot receives the current open state.

$ node --version
v24.18.0

To open a row while it streams and let the reader's click win, pass open ?? running.

<template>
  <UiTraceCollapsible :open="open ?? running" @update:open="open = $event">
    <UiTraceCollapsibleTrigger>
      <UiTraceLine :status="running ? 'running' : undefined">…</UiTraceLine>
    </UiTraceCollapsibleTrigger>
    <UiTraceCollapsibleContent>{{ text }}</UiTraceCollapsibleContent>
  </UiTraceCollapsible>
</template>

<script lang="ts" setup>
  defineProps<{ text: string; running: boolean }>();

  const open = ref<boolean>();
</script>

Wrap the UiTraceLine in an anchor. For a new tab, use an arrow-up-right icon and sr-only "(opens in a new tab)".

<template>
  <a href="https://docs.astro.build" target="_blank" rel="noreferrer">
    <UiTraceLine>
      <UiTraceTitle>
        Install Astro
        <span class="sr-only"> (opens in a new tab)</span>
      </UiTraceTitle>
      <UiTraceIcon name="lucide:arrow-up-right" />
    </UiTraceLine>
  </a>
</template>

Dialog

Wrap the UiTraceLine in the dialog's trigger. The dialog owns its open state, Escape and focus return.

Sheet

The same shape as the dialog. Drawer and Popover work the same way.

Group

Put rows that sit next to each other in a UiTrace. It also styles any trigger or link that wraps a UiTraceLine.

Searched for minimumReleaseAgeRead pnpm-workspace.yamlRan pnpm install

Sources

A collapsible row whose detail is a UiTrace of link rows.

See Sources for more examples.

Chain of Thought

A chain of thought is a collapsible row with step rows inside. Set the parent's status and title from its children.

Read the last twelve deploys

See Chain of Thought and Task for more examples.

Commit

A commit is a collapsible row with a line for each changed file. Say what changed in the title, Added, Edited or Deleted, and put the line counts in the description. Each file opens its diff in a Sheet.

Whole Turn

Three levels: the turn, a summary, and the rows. Text between steps sits between two UiTrace lists.

Ran node --version

Node is installed and pnpm is not. Reading the docs config.

Reasoning

Render a reasoning part from the AI SDK. The row is a UiTraceLine until the first text arrives. See Open State.

See Reasoning for more examples.

Tool

Render tool parts from the AI SDK. Map the tool part as in Tool.

See Tool for more examples.

Accessibility

Trace adds no roles of its own. Each line gets its semantics from the element that wraps it.

  • A UiTraceLine on its own is a span. It is read as text and is not a tab stop.
  • Wrap it in a UiTraceCollapsibleTrigger and it becomes a button with aria-expanded. Wrap it in a link, or in the trigger for a dialog or sheet, and it takes the keyboard and focus behavior of that element.
  • UiTraceIcon is hidden from assistive tech, so UiTraceTitle is the accessible name. Write it as a sentence that says what happened, like "Edited Trace.vue", not just "Trace.vue".
  • When a link opens a new tab, add "(opens in a new tab)" to the title with sr-only.
  • Status is shown with color and motion, so put it in the title too. Write "Running pnpm build" while it runs and "Failed to run pnpm build" when it errors.
  • The shimmer on a running title stops when the reader prefers reduced motion. The title still says what is happening.
  • UiTraceCollapsibleContent mutes its text. If you put a block with a muted background inside it, give the block text-foreground so it keeps its contrast. Code Block sets its own text color.

API Reference

Every part accepts class, and the parts built on a Reka Primitive also accept as and as-child.

UiTrace

A list of rows. It also styles any trigger or link that wraps a UiTraceLine.

PropTypeDefaultDescription
asstring | Component"div"The element to render.
as-childbooleanfalseRender the child instead of an element.
classstring-Additional classes to apply to the list.

UiTraceLine

One line: an icon and a title. It is a span, so it is not a button or a tab stop. Wrap it in a trigger or a link to make it do something.

PropTypeDefaultDescription
status"running" | "error" | "pending" | "success" | "warning"-The state of the work the line reports.
size"default" | "sm""default"The text size of the line.
asstring | Component"span"The element to render.
as-childbooleanfalseRender the child instead of an element.
classstring-Additional classes to apply to the line.

UiTraceIcon

A decorative icon slot, hidden from assistive tech. Before the title it names the action; after it, it is the indicator.

PropTypeDefaultDescription
namestring-An Iconify icon name. Used when the default slot is empty.
asstring | Component"span"The element to render.
classstring-Additional classes to apply to the icon slot.

UiTraceTitle

One sentence on one line. It truncates and shimmers while the line is running.

PropTypeDefaultDescription
asstring | Component"span"The element to render.
classstring-Additional classes to apply to the title.

UiTraceDescription

Secondary text after the title, such as a count or a duration. It does not truncate.

PropTypeDefaultDescription
asstring | Component"span"The element to render.
classstring-Additional classes to apply to the description.

UiTraceCollapsible

A row that expands. It accepts the props of UiCollapsible.

Prop / EventTypeDefaultDescription
openboolean-The controlled open state. Use with v-model:open.
default-openbooleanfalseWhether the row starts open.
unmount-on-hidebooleantrueSet to false to keep the detail mounted while closed, so nested rows keep their open state.
update:open(open: boolean) => void-Emitted when the open state changes.
classstring-Additional classes to apply to the row.

The default slot receives { open }.

UiTraceCollapsibleTrigger

The button that opens and closes the row. Put a UiTraceLine inside it. It adds a chevron after the line.

PropTypeDefaultDescription
chevronbooleantrueShow the trailing chevron.
chevron-iconstring"lucide:chevron-right"The Iconify icon used for the chevron.
classstring-Additional classes to apply to the trigger.
SlotDescription
defaultThe trace line.
chevronReplaces the chevron. Not rendered when chevron is false.

UiTraceCollapsibleContent

The detail of a row that expands.

PropTypeDefaultDescription
borderedbooleantrueShow the vertical rule and indent on the left of the content.
force-mountbooleanfalseAlways render the content, for use with your own animation library.
classstring-Additional classes to apply to the wrapper inside the animated container.
Keep nested rows open
To keep the detail mounted while closed, so nested rows keep their open state, set :unmount-on-hide="false" on the parent UiTraceCollapsible.