Skip to content
txbrendan/ui

Tool Call Card

beta

One 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

search_docs: Running

done

Input

{
  "query": "collapsible panel height",
  "limit": 3
}

Result

{
  "hits": 2,
  "top": [
    {
      "title": "Collapsible",
      "path": "docs/collapsible.md",
      "line": 42
    },
    {
      "title": "Accordion",
      "path": "docs/accordion.md",
      "line": 87
    }
  ]
}
search_docs: Done

failed

2 of 9 tests failed. The class override test expected gap-4.

run_tests: Failed

run

read_file: Done
edit_file: Done
run_tests: Running

name only

git_status: Done

Install

  1. 1. Add the registry to components.json, once per app. Without it, the shadcn CLI looks up @txbrendan in a public list that txbrendan/ui does not control.

    npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"
  2. 2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.

    npx shadcn@latest add @txbrendan/theme
  3. 3. 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

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." />