Agent activity
FreeA live line of what an agent is doing now, with a loading state.
pnpm dlx shadcn@latest add https://caliperui.site/r/agent-activity.json- 1.4 s
Done: Searching for “sortable table accessibility”
- 1.6 s
Done: Reading 3 pages
example.com, example.org, example.net
In progress: Writing the answer
Writing the answer
When to use #
Use it for
- Telling the user what a long-running agent is currently working on.
- Replacing a vague spinner with a named step.
Skip it when
- The task finishes in under a second.
- You need a full step history; use the agent run.
Installation #
pnpm dlx shadcn@latest add https://caliperui.site/r/agent-activity.json
Adds its 5 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.
Usage #
This is the code behind the preview above. It is built from AgentActivity and AgentLoading.
import { useState } from "react" import { AgentActivity, type ActivityStep } from "@/components/ui/agent-activity" const runSteps: ActivityStep[] = [ { id: "s1", label: "Searching for “sortable table accessibility”", status: "running", icon: "search" }, { id: "s2", label: "Reading 3 pages", status: "running", icon: "read" }, { id: "s3", label: "Writing the answer", status: "running" }, ]; export function AgentActivityDemo() { const [done] = useState(2); const [open, setOpen] = useState(false); const steps = runSteps.map<ActivityStep>((s, i) => ({ ...s, status: i < done ? "done" : i === done ? "running" : "running", duration: i < done ? `${[1.4, 1.6, 1.4][i]} s` : undefined, detail: i === 1 && i < done ? "example.com, example.org, example.net" : undefined })); const visible = steps.slice(0, Math.min(3, done + 1)).map((s, i) => (i < done ? { ...s, status: "done" as const } : s)); return ( <AgentActivity steps={visible} open={open} onOpenChange={setOpen} summary={done >= 3 ? "Worked for 4.4 s · 3 steps" : undefined} /> ); }
API reference #
AgentActivity
component
AgentLoading
component
Accessibility #
It exposes status semantics, with aria-label, aria-expanded, aria-controls and aria-hidden kept in step with state. Changes that matter are announced through a live region.
No custom key handling; Tab and the native activation keys do the work.
Motion #
It checks prefers-reduced-motion itself and settles immediately instead of travelling. Every state is still reachable.