Tool result
FreeThe outcome of a tool call, collapsed to a summary and expandable to detail.
pnpm dlx shadcn@latest add https://caliperui.site/r/tool-result.json> caliper@0.4.0 test> vitest run
✓ src/counter.test.tsx (4 tests) 38ms ✓ src/table.test.tsx (12 tests) 91ms ✓ src/tree.test.tsx (9 tests) 64ms ✗ src/thread.test.tsx (6 tests | 1 failed) 120ms → expected "Not sent" but received "Sending…"
Test Files 1 failed | 3 passed (4) Tests 1 failed | 30 passed (31) Duration 1.02sWhen to use #
Use it for
- An agent calls tools and the user may want to inspect the output.
- You want success and failure to read at a glance.
Skip it when
- The output is the answer itself; show it as a message.
Installation #
terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/tool-result.json
Adds its 7 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.
example.tsx
import { ToolResult } from "@/components/ui/tool-result" const output = `> caliper@0.4.0 test > vitest run ✓ src/counter.test.tsx (4 tests) 38ms ✓ src/table.test.tsx (12 tests) 91ms ✓ src/tree.test.tsx (9 tests) 64ms ✗ src/thread.test.tsx (6 tests | 1 failed) 120ms → expected "Not sent" but received "Sending…" Test Files 1 failed | 3 passed (4) Tests 1 failed | 30 passed (31) Duration 1.02s `; export function ToolResultDemo() { return ( <ToolResult name="runTests" kind="error" summary="1 failed, 30 passed" duration="1.0 s" output={output} defaultOpen /> ); }
API reference #
ToolResult
component
PropTypeDefaultDescription
name *string—
summarystring—One line shown while collapsed, such as "12 files matched".
kindToolResultKind"text"
outputunknown—A string for text and error, any JSON value for json, rows for table.
columnsreadonly string[]—Column headings for table output; each row is an object or an array.
durationstring—
defaultOpenbooleanfalse
childrenReactNode—Replaces the body for kind "custom".
classNamestring—
Accessibility #
It is built on native elements and keeps aria-label, aria-expanded, aria-controls and aria-hidden in step with state.
No custom key handling; Tab and the native activation keys do the work.
Motion #
Transitions use the shared duration and easing tokens. Under prefers-reduced-motion those tokens collapse to instant and travel distances go to zero, so state changes still happen without movement.