Progress Tracker

Real-time status feedback for multi-step operations.
  1. Building
    Compiling TypeScript and bundling assets
  2. Running Tests
    147 tests across 23 suites
  3. Deploy to Production
    Upload to edge nodes
<ProgressTracker  id="progress-tracker-in-progress"  steps={[      {          "id": "build",          "label": "Building",          "description": "Compiling TypeScript and bundling assets",          "status": "completed"      },      {          "id": "test",          "label": "Running Tests",          "description": "147 tests across 23 suites",          "status": "in-progress"      },      {          "id": "deploy",          "label": "Deploy to Production",          "description": "Upload to edge nodes",          "status": "pending"      }  ]}  elapsedTime={43200}/>

Getting Started

Run this once from your project root.

npx shadcn@latest add @tool-ui/progress-tracker

Render ProgressTracker in your UI with tool-compatible props.

import { ProgressTracker } from "@/components/tool-ui/progress-tracker";export function Example() {  return (    <ProgressTracker      id="progress-tracker-example"      steps={[        {          id: "build",          label: "Building",          description: "Compiling TypeScript and bundling assets",          status: "completed",        },        {          id: "test",          label: "Running Tests",          description: "147 tests across 23 suites",          status: "in-progress",        },        {          id: "deploy",          label: "Deploy to Production",          description: "Upload to edge nodes",          status: "pending",        },      ]}      elapsedTime={43200}    />  );}

Register this renderer so tool results display as ProgressTracker.

"use client";import { type Toolkit } from "@assistant-ui/react";import { ProgressTracker } from "@/components/tool-ui/progress-tracker";import { safeParseSerializableProgressTracker } from "@/components/tool-ui/progress-tracker/schema";import { createResultToolRenderer } from "@/components/tool-ui/shared";export const toolkit: Toolkit = {  trackProgress: {    type: "backend",    render: createResultToolRenderer({      safeParse: safeParseSerializableProgressTracker,      render: (parsedResult) => <ProgressTracker {...parsedResult} />,    }),  },};

These snippets use assistant-ui for end-to-end wiring, but the ProgressTracker component itself is framework-agnostic at the UI layer: you can use it in any React codebase with any LLM SDK or tool-calling interface that can provide compatible props.

ProgressTracker v2 is display-only and result-driven: render it from backend tool result updates. For interactive decisions or confirmations, use dedicated decision surfaces like Option List or Preferences Panel.

Key Features

Status indicators

Visual states for pending, in-progress, completed, and failed steps

Elapsed time

Optional time tracking with automatic formatting

Error handling

Failed step indicators with descriptive error messages

Receipt state

Terminal state view showing complete operation history

Step Statuses

Each step has one of four statuses:

  • Pending — Not yet started (empty circle)
  • In-progress — Currently executing (animated spinner)
  • Completed — Successfully finished (filled checkmark)
  • Failed — Encountered an error (filled X icon)

The component automatically highlights the current step (first in-progress, otherwise first failed, otherwise first pending) with a subtle background and aria-current="step" for accessibility.

Receipt Pattern

Use the choice prop to render a terminal state after an operation completes, fails, or is cancelled. The receipt displays the full step history with an outcome indicator, which works well in conversation history.

Receipt features:

  • Displays all steps with final statuses and connecting lines
  • Shows elapsed time badge at the top (if provided)
  • Outcome indicator in top-right: green check (success), red alert (failure), gray check (cancelled)
  • Supports success, partial, failed, and cancelled outcomes
  • Read-only with no action buttons
  • Uses role="status" for screen reader announcements

Elapsed Time

Pass elapsedTime in milliseconds to display a timer badge. Automatically formatted as:

  • Under 60 seconds: 3.4s
  • Over 60 seconds: 2m 15s

Props

Prop

Type

ProgressStep Schema

Prop

Type

ToolUIReceipt Schema

Prop

Type

Accessibility

  • Semantic <article> with role="status" and aria-live="polite" for live updates
  • aria-busy indicates when an operation is in progress
  • aria-current="step" marks the currently active step
  • Steps rendered as semantic ordered list (<ol> / <li>)
  • Elapsed duration is rendered with semantic <time> and machine-readable dateTime
  • All animations respect prefers-reduced-motion
  • Text is unselectable to prevent accidental highlighting during status changes