# ToolCallTimeline

> Every tool call with its state, a measured duration and a waterfall; errors inline.

Source: https://agent-ui-kit-demo.vercel.app/docs/components/tool-call-timeline

## Installation

From npm:

```bash
npm i @dgesteves/agent-ui-kit ai
```

```tsx
import { ToolCallTimeline } from '@dgesteves/agent-ui-kit';
import '@dgesteves/agent-ui-kit/styles.css'; // once per app, or @import '@dgesteves/agent-ui-kit/tailwind.css' with Tailwind v4
```

Or as source, with the shadcn CLI:

```bash
npx shadcn@latest add @agent-ui-kit/tool-call-timeline
```

```tsx
import { ToolCallTimeline } from '@/components/agent-ui/tool-call-timeline';
```

## Usage

```tsx
<ToolCallTimeline
  parts={message.parts}
  tools={{
    read_file: { label: 'Read file', summary: (input) => (input as { path?: string }).path },
    run_command: { label: 'Run command', risk: 'high' },
  }}
  // Once the run has ended, calls that never settled read "Stopped".
  active={status === 'submitted' || status === 'streaming'}
/>
```

## API reference

### ToolCallTimeline

A vertical timeline of tool calls with live states, durations, a waterfall,
and expandable input/output. Follows the WAI-ARIA disclosure pattern; Arrow
Up/Down, Home and End move between calls.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `parts` (required) | `readonly AnyUIPart[]` |  | Tool parts, or every part of a message: non-tool parts are ignored. |
| `tools` | `Record<string, ToolMeta>` |  |  |
| `timings` | `ToolTimings` |  | Externally measured timings by `toolCallId`. Measured client-side when omitted. |
| `expanded` | `readonly string[]` |  | Controlled set of expanded `toolCallId`s. |
| `defaultExpanded` | `readonly string[]` |  |  |
| `onExpandedChange` | `(expanded: string[]) => void` |  |  |
| `expandErrors` | `boolean` | `false` | Expand calls automatically when they fail. Default `false`: the error message is always shown inline under a failed call, with details on demand. |
| `waterfall` | `boolean` | `true` | Show a per-call waterfall bar relative to the whole timeline. |
| `announce` | `boolean` | `true` | Announce completions and failures to screen readers. |
| `renderExtra` | `(part: ToolPart) => ReactNode` |  | Extra content under a call, e.g. an approval card. |
| `label` | `string` | `'Tool calls'` | Accessible name for the list. |
| `active` | `boolean` | `true` | Whether the run can still make progress. Pass `false` once it has ended (stopped, failed, or restored from history): calls still streaming their input or running then read "Stopped" and their clocks stop, instead of counting up forever. |

Other props go to the root `<div>`: `className`, `id`, `aria-*`, `data-*` and event handlers.

### ToolMeta

Per-tool presentation. Every field is optional.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` | `string` |  | Display label. Defaults to the humanized tool name. |
| `icon` | `ReactNode` |  |  |
| `summary` | `(input: unknown, part: ToolPart) => ReactNode` |  | One-line summary shown next to the label. Defaults to the most descriptive input field. Not called before any input has arrived; while the input streams it can be partial. |
| `renderOutput` | `(output: unknown, part: ToolPart) => ReactNode` |  | Replace the default JSON output view. |
| `risk` | `RiskLevel \| ((input: unknown) => RiskLevel)` |  | Risk shown on approval requests for this tool. |

### ToolTiming

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `startedAt` | `number` |  | First time the call was observed (input started streaming). |
| `runningAt` | `number` |  | When execution began: input complete, or approval granted. |
| `endedAt` | `number` |  | When the call settled (output, error or denial). |

### RiskLevel

```ts
type RiskLevel = 'low' | 'medium' | 'high' | 'critical';
```

## Accessibility

| Keys | Action |
| --- | --- |
| ↑ ↓ | Previous or next call |
| Home End | First or last call |
| Enter Space | Show or hide the call’s input and output |

- An ordered list named by `label` ("Tool calls"). Each call is a disclosure button with `aria-expanded`, as in the WAI-ARIA accordion pattern; the arrow keys move between them.
- A call’s name, summary, state and duration are in its button’s accessible name. In narrow containers the summary is hidden visually but still read.
- Completions and failures are announced through a polite live region, such as "Read file finished in 1.2 seconds" or "Read file failed: ENOENT…". Turn it off with `announce={false}` when something else announces them.
- States are never color alone: each has an icon and a word ("Failed", "Needs approval", "Denied").
- The expand and collapse animation runs only without `prefers-reduced-motion`.

## Theming

Slots (`data-slot`): `tool-call-trigger`, `tool-call-timeline`, `tool-call`.

- `data-phase` on `tool-call`: 'streaming' | 'running' | 'awaiting-approval' | 'success' | 'error' | 'denied'
- `data-state` on `tool-call`: 'input-streaming' | 'input-available' | 'approval-requested' | 'approval-responded' | 'output-available' | 'output-error' | 'output-denied'
- `data-interrupted` on `tool-call`: set once the run ended before the call settled

Tokens it uses: `--aui-accent`, `--aui-accent-fg`, `--aui-bg`, `--aui-border`, `--aui-border-strong`, `--aui-fg`, `--aui-fg-muted`, `--aui-fg-subtle`, `--aui-font-mono`, `--aui-font-sans`, `--aui-hot`, `--aui-hot-fg`, `--aui-ring`, `--aui-surface-2`. See https://agent-ui-kit-demo.vercel.app/docs/getting-started#theming.
