suiss/ui · Component
Trace
Rows for the steps an agent takes: reasoning, tool calls, sources, plans and file edits.
Trace is an open-source component from suiss/ui for React, React Native, SwiftUI and Jetpack Compose. The @esuiss/ui CLI copies its source into your project, so you own the code.
A Trace is a list of TraceLine rows. Each row has a TraceIcon, a TraceTitle, and an optional TraceDescription and status. A row can expand to show more detail, link to a page, or open a dialog or sheet.
Every row 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, such as calling a tool, running a subagent or editing a file. Use Message for its reply and Marker for notes and dividers between turns.
Installation
CLI
Works in any project with a components.json. See Installation for the one-line registry setup. Or use the suiss/ui CLI:
Manual
-
Add Collapsible and the
cnhelper. -
Copy the source into
components/ui/trace.tsx:
- Update the import paths to match your project.
Usage
Wrap the row in a TraceCollapsible to show more detail when it expands. Put the TraceLine inside TraceCollapsibleTrigger and the detail in TraceCollapsibleContent:
TraceLine is always the row. To make a row do something, wrap it in that thing's trigger: a link, a DialogTrigger, a SheetTrigger, a drawer or a popover.
Rows start closed. Set defaultOpen on TraceCollapsible to start open, or pass open with onOpenChange to control it. Set keepMounted on TraceCollapsibleContent so nested rows keep their open state while the parent is closed.
Rows start closed. Set defaultOpen on TraceCollapsible to start open, or pass open with onOpenChange to control it.
Rows start closed. Set defaultExpanded on TraceCollapsible to start open, or pass isExpanded with onExpandedChange to control it.
Examples
Static
A TraceLine on its own, for a step with no detail to show. It reads as plain text.
Status
Set status on TraceLine to running, error or pending. Leave it unset for finished work, and say the state in the title too: "Running pnpm build", "Failed to run pnpm lint", "Run pnpm test".
Description
Secondary text such as a diff stat, a duration or a count, after the title. It does not truncate.
Collapsible
A row that expands to show the command output.
Controlled
Opens and closes a row from outside. To open a row while it streams and still let the reader close it, pass the reader's choice and fall back to the running state.
Link
Wraps the TraceLine in an anchor. For a new tab, use an arrow icon and add "(opens in a new tab)" to the title with sr-only.
Dialog
Wraps the TraceLine in a DialogTrigger. The dialog owns its open state, Escape and focus return.
Sheet
The same shape as the dialog, in a sheet.
Group
Rows next to each other in one Trace, which also styles any trigger or link that wraps a TraceLine.
Sources
A collapsible row whose detail is a Trace of link rows.
Steps
A summary row with step rows inside. The parent's status and title come from its children.
Commit
A row for each changed file, with 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 Trace lists.
Reasoning
A thinking row that expands into the reasoning text.
Tool calls
Tool calls with their input and output, including a failed call.
API Reference
Trace
A list of rows. It also styles any trigger or link that wraps a TraceLine.
Also accepts the props of React.ComponentProps<"div">.
TraceLine
One row: an icon and a title. It is a span, so it is not a button or a tab stop.
| Prop | Type | Default | Description |
|---|---|---|---|
status | "running" | "error" | "pending" | — | The state of the work the row reports. running shimmers the title, error turns it destructive and pending mutes it. |
Also accepts the props of React.ComponentProps<"span">.
TraceIcon
A decorative icon slot, hidden from assistive tech. Before the title it names the action; after it, it is the indicator.
Also accepts the props of React.ComponentProps<"span">.
TraceTitle
One sentence on one line. It truncates, and shimmers while the row is running.
Also accepts the props of React.ComponentProps<"span">.
TraceDescription
Secondary text after the title, such as a count or a duration. It does not truncate.
Also accepts the props of React.ComponentProps<"span">.
TraceCollapsible
A row that expands.
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | The controlled open state. Pass it with onOpenChange. |
defaultOpen | boolean | false | Whether the row starts open. |
onOpenChange | (open: boolean) => void | — | Called when the open state changes. |
| Prop | Type | Default | Description |
|---|---|---|---|
isExpanded | boolean | — | The controlled open state. Pass it with onExpandedChange. |
defaultExpanded | boolean | false | Whether the row starts open. |
onExpandedChange | (isExpanded: boolean) => void | — | Called when the open state changes. |
Also accepts the props of Collapsible.
TraceCollapsibleTrigger
The button that opens and closes the row. Put a TraceLine inside it; it adds a chevron after the line.
Also accepts the props of CollapsibleTrigger.
TraceCollapsibleContent
The detail of a row that expands, indented under the title.
| Prop | Type | Default | Description |
|---|---|---|---|
keepMounted | boolean | false | Keeps the detail mounted while closed, so nested rows keep their open state. |
Also accepts the props of CollapsibleContent.
Accessibility
- Trace adds no roles of its own. Each row gets its semantics from the element that wraps it.
- A
TraceLineon its own is read as text and is not a tab stop. - Inside
TraceCollapsibleTriggerthe row is a button witharia-expanded. Inside a link or a dialog or sheet trigger, it takes that element's keyboard and focus behavior. TraceIconis hidden from assistive tech, soTraceTitleis the accessible name. Write it as a sentence that says what happened, such as "Edited trace.tsx", not just "trace.tsx".- Status is shown with color and motion, so put it in the title too.
- The running shimmer stops when the reader prefers reduced motion.
Notes
- Styling hooks:
data-slot="trace","trace-line","trace-icon","trace-title","trace-description","trace-collapsible","trace-collapsible-trigger"and"trace-collapsible-content", plusdata-statuson the row. TraceCollapsibleContentmutes its text. Give a block with a muted background inside ittext-foregroundto keep its contrast; Code Block sets its own text color.
A Trace is a column of TraceLine rows. Each row has a TraceIcon, a TraceTitle and an optional TraceDescription and status. Wrap a row in TraceCollapsible to show more detail when it expands, or in a Pressable to open a link or a sheet.
Use Trace for the steps an agent takes, such as calling a tool, running a command or editing a file. Use Message for its reply and Marker for notes between turns.
Installation
The CLI also adds what it builds on: Icon, Text.
Manual
-
Target iOS 17 or later.
-
Copy the theme files every view uses:
- Copy the source and every file it uses:
- Add the files to your app target.
- Set
minSdkto 24 or higher and add the dependencies:
- Copy the theme files every view uses:
- Copy the source and every file it uses:
- Update the
com.esuiss.uipackage names to match your project.
Usage
Rows start closed. Set defaultOpen on TraceCollapsible to start open, or pass open with onOpenChange to control it. In SwiftUI use TraceCollapsible(initiallyExpanded:) or TraceCollapsible(isExpanded:); in Compose pass initiallyExpanded or expanded with onExpandedChange.
Examples
Static
A TraceLine on its own, for a step with no detail to show.
Status
running pulses the title, error turns the row destructive and pending dims it. Say the state in the title too.
Description
Secondary text such as a diff stat, a duration or a count after the title.
Collapsible
A row that expands to show the command output.
Controlled
Opens and closes a row from outside with open and onOpenChange.
Link
Wraps the TraceLine in a Pressable that opens a URL.
Group
Rows next to each other in one Trace.
Sources
A collapsible row whose detail is a Trace of link rows.
Steps
A summary row with step rows inside.
Commit
A row for each changed file, with the line counts in the description.
Whole turn
Three levels: the turn, a summary and the rows, with text between the steps.
Reasoning
A thinking row that expands into the reasoning text.
Tool calls
Tool calls with their output, including a failed call.
API Reference
Trace
A column of rows.
Also accepts the props of ViewProps.
TraceLine
One row: an icon, a title and an optional description.
| Prop | Type | Default | Description |
|---|---|---|---|
status | "running" | "error" | "pending" | — | The state of the work the row reports. |
Also accepts the props of ViewProps.
TraceIcon
A 16 pt icon slot, hidden from assistive technology.
Also accepts the props of ViewProps.
TraceTitle
One line of text that truncates. It pulses while the row is running unless the reader prefers reduced motion.
Also accepts the props of Text.
TraceDescription
Secondary text after the title, with tabular numbers.
Also accepts the props of Text.
TraceCollapsible
A row that expands.
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | The controlled open state. Pass it with onOpenChange. |
defaultOpen | boolean | false | Whether the row starts open. |
onOpenChange | (open: boolean) => void | — | Called when the open state changes. |
TraceCollapsibleTrigger
The pressable row that opens and closes the detail. It adds a chevron after the line.
TraceCollapsibleContent
The detail of a row, indented under the title with a leading rule.
| Prop | Type | Default | Description |
|---|---|---|---|
keepMounted | boolean | false | Keeps the detail mounted while closed, so nested rows keep their state. |
Accessibility
- The trigger is a button whose state reads as expanded or collapsed.
TraceIconis hidden from assistive technology, so write the title as a sentence that says what happened.- Status is shown with color and motion, so put it in the title too.