XDSChatToolCalls@xds/core · Chat
Preview coming soon
Usage
ChatToolCalls displays tool or function call invocations from an LLM response. Pass an array of calls and the component handles the rest — a single call renders inline, while multiple calls collapse into a summary with the latest call visible at the surface. Use it anywhere an AI agent shows what actions it took.Best practices
| Guidance | Practices |
|---|---|
| Do | Include a target string on every call so the user can see what the tool acted on — a file path, a shell command, or a search query. |
| Do | Show a duration on completed calls so users can judge which tools are slow and understand why a response took time. |
| Do | Provide resultDetail with a code block for calls that produce output — diffs for edits, terminal output for shell commands — so users can inspect results inline. |
| Do | Set a unique key on each call item when streaming so React can animate additions without re-mounting completed rows. |
| Don't | Don't omit the status field — without it the call defaults to complete, which is misleading for calls that are still running or have failed. |
| Don't | Don't display tool calls outside a chat message context — they are designed to sit inside an assistant message, not as standalone UI. |
| Don't | Don't use custom wrappers around individual calls — the component handles single vs. grouped layout automatically based on the array length. |
Anatomy
| Element | Description | |
|---|---|---|
| Status icon | required | A colored circle with a check, cross, or spinner indicating whether the call is pending, running, complete, or errored. |
| Tool name | required | The function or tool name displayed in monospace — bash, edit, read, web_search, etc. |
| Node badge | A neutral pill badge showing which sandbox or environment ran the tool, like cli:remote-server or workspace. | |
| Target label | The target of the action — a file path, command, or search query — shown after the tool name. | |
| Diff stats | Green additions and red deletions counts for edit operations, displayed inline after the target. | |
| Duration | Execution time shown on the trailing edge for completed calls. | |
| Group header | A wrench icon with a call count, shown when multiple calls are present. Clicking toggles between the summary and the full list. |
Import
tsimport {XDSChatToolCalls} from '@xds/core/Chat'
Props
| Prop | Type | Description |
|---|---|---|
callsrequired | XDSChatToolCallItem[] | Array of tool call data. Each item has name, status, target, duration, node, additions, deletions, stats, errorMessage, resultDetail, key, and data. |
label | string | Custom summary label for groups. Auto-generated from count if omitted. |
isExpanded | boolean | Controlled expanded state for the group. |
defaultIsExpanded | boolean (default: false) | Default expanded state when uncontrolled. |
onExpandedChange | (isExpanded: boolean) => void | Callback fired when the expanded state changes. |
Examples
Common configurations, variations, and states.ChatToolCalls — ExpandableTool calls with expandable result details showing diffs and command output in code blocks. Click a row to reveal its result.
tsx'use client';import {XDSChatToolCalls} from '@xds/core/Chat';import {XDSCodeBlock} from '@xds/core/CodeBlock';const editDiff = `--- a/src/utils/formatDate.ts+++ b/src/utils/formatDate.ts@@ -8,7 +8,11 @@-export function formatDate(date: Date): string {- return date.toLocaleDateString();-}+export function formatDate(+ date: Date,+ locale = 'en-US',+ options?: Intl.DateTimeFormatOptions,+): string {+ return new Intl.DateTimeFormat(locale, options).format(date);+}`;const testOutput = `$ yarn testPASS src/utils/formatDate.test.tsPASS src/components/DatePicker.test.tsxTest Suites: 2 passed, 2 totalTests: 14 passed, 14 totalTime: 1.8s`;export default function ChatToolCallsInteractiveToolCalls() {return (<XDSChatToolCallsdefaultIsExpandedcalls={[{name: 'edit',target: 'src/utils/formatDate.ts',status: 'complete',duration: '85ms',node: 'cli:remote-server',additions: 6,deletions: 3,resultDetail: (<XDSCodeBlockcode={editDiff}language="typescript"maxHeight="50vh"/>),},{name: 'bash',target: 'yarn test',status: 'complete',duration: '1.8s',node: 'cli:remote-server',resultDetail: (<XDSCodeBlock code={testOutput} language="bash" maxHeight="50vh" />),},{name: 'web_search',target: 'Intl.DateTimeFormat locale options',status: 'complete',duration: '1.2s',},]}/>);}
ChatToolCalls — SimpleA single inline tool call above a collapsible multi-call group with diff stats. Shows both layouts side by side.
tsx'use client';import {XDSChatToolCalls} from '@xds/core/Chat';import {XDSStack} from '@xds/core/Layout';export default function ChatToolCallsSimple() {return (<XDSStack direction="vertical" gap={4}><XDSChatToolCallscalls={[{name: 'bash',target: 'git status',status: 'complete',duration: '1.2s',},]}/><XDSChatToolCallsdefaultIsExpandedcalls={[{name: 'read',target: 'src/components/DataGrid.tsx',status: 'complete',duration: '30ms',},{name: 'edit',target: 'src/components/DataGrid.tsx',status: 'complete',duration: '85ms',additions: 24,deletions: 8,},{name: 'edit',target: 'src/components/DataGrid.test.tsx',status: 'complete',duration: '60ms',additions: 45,},]}/></XDSStack>);}
ChatToolCalls — StatusesAll four status states — pending, running, complete, and error — shown together in a single group.
tsx'use client';import {XDSChatToolCalls} from '@xds/core/Chat';export default function ChatToolCallsStatuses() {return (<XDSChatToolCallsdefaultIsExpandedcalls={[{key: 'pending',name: 'bash',target: 'yarn build',status: 'pending',},{key: 'running',name: 'bash',target: 'yarn test',status: 'running',},{key: 'complete',name: 'edit',target: 'src/App.tsx',status: 'complete',duration: '120ms',additions: 8,deletions: 2,},{key: 'error',name: 'bash',target: 'yarn lint',status: 'error',duration: '0.8s',errorMessage: '3 lint errors found',},]}/>);}
Showcase source
tsx'use client';import {XDSChatToolCalls} from '@xds/core/Chat';export default function ChatToolCallsShowcase() {return (<XDSChatToolCallsdefaultIsExpandedcalls={[{name: 'bash',target: 'git diff --stat',status: 'complete',duration: '340ms',},{name: 'read',target: 'src/utils/formatDate.ts',status: 'complete',duration: '45ms',},{name: 'edit',target: 'src/utils/formatDate.ts',status: 'complete',duration: '120ms',additions: 12,deletions: 3,},]}/>);}