Tool Call Card
betaOne tool call an agent made, on one line: its status, the tool, its inputs in a few words, and how long it took. It opens to the inputs and the result.
Preview
running
done
{
"query": "collapsible panel height",
"limit": 3
}{
"hits": 2,
"top": [
{
"title": "Collapsible",
"path": "docs/collapsible.md",
"line": 42
},
{
"title": "Accordion",
"path": "docs/accordion.md",
"line": 87
}
]
}failed
2 of 9 tests failed. The class override test expected gap-4.
run
name only
Install
1. Add the registry to
components.json, once per app. Without it, the shadcn CLI looks up@txbrendanin a public list that txbrendan/ui does not control.npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.
npx shadcn@latest add @txbrendan/theme3. Add the component.
npx shadcn@latest add @txbrendan/tool-call-card
Use it for
- In an agent's chat or run log, one card per tool call: what it called, with what, and what came back.
- Pass status running while the call runs, then done or failed. running spins, done is a green check, and failed is red.
- Keep summary to a few words, like the search query or the file name. The full inputs go in input.
- Pass input and result as the objects the tool took and gave. They show as JSON when the card opens. Pass a node to show them your own way.
- On failed, pass error in plain words, like Timed out after 30s. It shows under the line, so no one has to open the card to see it.
- Stack several in a flex column with a small gap for a run of calls.
Avoid it for
- The agent's own words or reasoning. Use ThinkingState for its steps.
- A step that needs a person to say yes before it runs. Ask for approval first, then show the call.
- A status on a row or in a table. Use StatusText.
Props
- name
Required. The tool's name, like "search_docs". Shown in mono type.
string
- status
Required. Where the call stands. running spins in the brand tone, done is a success check, and failed is danger red.
"running" | "done" | "failed"
- summary
The inputs in a few words, like "collapsible panel height". Shown on the closed line, cut short with an ellipsis.
ReactNode
- input
The full inputs, shown when the card opens. An object or array shows as JSON.
ReactNode | Record<string, unknown> | unknown[]
- result
What came back, shown when the card opens. An object or array shows as JSON. While running, the card says it is waiting.
ReactNode | Record<string, unknown> | unknown[]
- error
failed: what went wrong, in plain words. It shows under the line, open or closed.
ReactNode
- duration
How long the call took, or has run so far, like "1.5s". Update it while running for a live timer.
string
- defaultOpen
Starts open.
boolean · default false
- open
Controls whether it is open. Pair it with onOpenChange.
boolean
- onOpenChange
Called when the card opens or closes.
(open: boolean) => void
- disabled
The line can't be opened.
boolean · default false
- className
Extra classes on the card. Later classes win.
string
| Prop | Type | Default | What it does |
|---|---|---|---|
| name | string | - | Required. The tool's name, like "search_docs". Shown in mono type. |
| status | "running" | "done" | "failed" | - | Required. Where the call stands. running spins in the brand tone, done is a success check, and failed is danger red. |
| summary | ReactNode | - | The inputs in a few words, like "collapsible panel height". Shown on the closed line, cut short with an ellipsis. |
| input | ReactNode | Record<string, unknown> | unknown[] | - | The full inputs, shown when the card opens. An object or array shows as JSON. |
| result | ReactNode | Record<string, unknown> | unknown[] | - | What came back, shown when the card opens. An object or array shows as JSON. While running, the card says it is waiting. |
| error | ReactNode | - | failed: what went wrong, in plain words. It shows under the line, open or closed. |
| duration | string | - | How long the call took, or has run so far, like "1.5s". Update it while running for a live timer. |
| defaultOpen | boolean | false | Starts open. |
| open | boolean | - | Controls whether it is open. Pair it with onOpenChange. |
| onOpenChange | (open: boolean) => void | - | Called when the card opens or closes. |
| disabled | boolean | false | The line can't be opened. |
| className | string | - | Extra classes on the card. Later classes win. |
Accessibility
- The line is one button. It says the status in words, the tool, the summary, and the time, and it tells screen readers if it is open.
- Enter or Space opens and closes it.
- Status is shown three ways: words for screen readers, an icon shape (a spinner, a check, or a circle with a mark), and a color.
- A change of status is said once, politely, in a hidden status region: search_docs: Done.
- The error is plain text under the line, so it is read without opening the card.
- The spinner stops when the theme turns motion off, and for reduced motion. The panel then opens at once.
Examples
Running
<ToolCallCard name="search_docs" status="running" summary="collapsible panel height" duration="0.8s" />Done, with input and result
<ToolCallCard
name="search_docs"
status="done"
summary="collapsible panel height"
duration="1.2s"
input={{ query: "collapsible panel height", limit: 3 }}
result={{ hits: 2, top: ["docs/collapsible.md", "docs/accordion.md"] }}
/>Failed
<ToolCallCard name="run_tests" status="failed" summary="card.test.tsx" duration="4.2s" error="2 of 9 tests failed." />