Skip to content
WingoUI
ComponentsTemplatesDocsPricingAI agentsBlogChangelogContact
Components
Buttons & Actions
ButtonButton GroupCopy ButtonDelete ButtonTheme ToggleToggleToggle Group
Inputs
Avatar UploadCalendarCheckboxColor PickerComboboxCountry SelectCron PickerCurrency InputDate PickerDate Range PickerDate Time PickerDuration PickerEmail InputEmoji PickerFile UploadFilter BuilderInputInput GroupListboxMasked InputMention InputMonth PickerMulti SelectNumber InputOTP InputPassword InputPhone InputRadio GroupRatingSearch InputSegmented ControlSelectSignature PadSliderSwitchTag InputTextareaTime PickerTimezone SelectTree Select
Forms
Address InputBooking WidgetCSV ImportFieldForm WizardInline EditInvoice line itemsRich Text EditorSchema Builder
Navigation
Back To TopBounce SidebarBreadcrumbCommand MenuGlobal SearchGooey NavHook SidebarNav MenuNav TabsPaginationProximity SidebarScroll ProgressSidebarStepsTable Of ContentsTabsTopbarUser MenuWorkspace Switcher
Overlays
Alert DialogContext MenuDialogDrawerDropdown MenuFamily DrawerHover CardPopoverShare DialogSheetShortcuts DialogTooltipTour
Feedback
AlertBannerCookie ConsentEmoji ReactionEmpty StateNotification BellNotification CenterProgressRoute ProgressSetup ChecklistSkeletonSpinnerToast
Data Display
Approval FlowAvatarBadgeCalendar ViewCode BlockComment ThreadContact cardCountdownDescription ListDiff ViewerFile ListFile managerFolderGanttJSON ViewerKbdLog ViewerMarkdownPresenceSchedulerTagTimelineTree View
Tables & Lists
Audit LogData TableDeal PipelineEditable GridKanbanListMembers tablePermissions MatrixTableTask ListVirtual List
Charts & Stats
Animated CounterArea chartBar chartDonut chartFunnel chartGaugeGitHub ActivityHeatmap calendarLeaderboardLine chartRadar chartRadial barSparklineStat CardTrackerTrend badge
Layout
AccordionApp ShellCardCollapsibleDetail LayoutEntity HeaderPage HeaderScroll AreaSeparatorSettings LayoutSplit ViewToolbar
Media
Audio PlayerCarouselCSV ViewerDOCX EditorDOCX ViewerExcel ViewerFile SystemImage compareImage CropperImage GalleryImage LightboxLocation MapPDF ViewerPowerPoint ViewerQR CodeStep PlayerVideo Player
AI Kit
Agent Status CardChat MessageChat ThreadChat WidgetConversation ListFluid OrbGrid RevealMatrix OrbModel PickerPrompt InputReasoning IndicatorRule BuilderSuggestion ChipsTool Call TimelineUsage MeterVoice InputWorkflow Canvas
Text & Effects
Background PatternGravity LettersMarqueeTerminalText AnimateText Rotate
Mobile
Action SheetBottom Tab BarFABHaptic ButtonHero HeaderInstall PromptLarge Title HeaderNotification BannerOnboarding CarouselPicker WheelPull To RefreshSlide To ConfirmSticky CTA BarSwipe DeckSwipeable Tabs
Commerce
Cart drawerCategory pickerCheckout stepsCoupon inputFavorite buttonFilter panelListing cardListing gridOrder trackerPricePrice rangePricing tableProduct galleryQuantity stepperReviewsSeller card
Marketing Sections
App Download SectionBlog Cards SectionCTA SectionFAQ SectionFeature GridFeature ShowcaseHero SectionIntegrations SectionLogo CloudMarketing FooterMarketing HeaderMarketing SectionNewsletter SectionPricing SectionStats SectionSteps SectionTeam SectionTestimonials SectionTimeline SectionVideo Section
Blocks
Admin Dashboard PageAdmin ShellAI Chat PageAPI Keys PageAutomation Builder PageCheckout PageCRM Contact PageCRM Pipeline PageError PagesInbox PageInvoice PageKPI DashboardListing Detail PageLogin PageMarketplace Home PageMarketplace Search PageMarketplace ShellMobile App HomeOnboarding FlowOrder History PagePost Listing WizardPricing PageProfile PageRegister PageSettings PageUsers Admin Page
Templates
About PageAcademy PageAccessibility PageAffiliate PageAgency PageAI Product PageAppointment Booking PageBlog PageBlog Post PageBug Bounty PageCareers PageChangelog PageCommunity PageCompare PageContact PageCustomer Story PageCustomers PageDemo Booking PageDevelopers PageDocs Home PageDownload PageEnterprise PageEvents PageExperts PageFAQ PageFeature PageGlossary PageHelp Article PageHelp Center PageHome Services PageImpact PageIntegration Detail PageIntegrations PageJob Detail PageLanding PageLaunch PageLegal PageManifesto PagePortfolio PagePress PageProduct Tour PagePromo PageReal Estate PageReferral PageResearch Report PageRestaurant PageRoadmap PageROI Calculator PageSecurity PageSolutions PageStartups PageStatus PageStorefront PageSwitch PageTemplate Gallery PageTravel PageWaitlist PageYear in Review Page
Hooks & Utilities
AI ChatChart kitCommerceDate utilsFile exportFile typesFiltersForm validationHapticsInvoicingMotion presetsNavigationNumber formatRelative timeRomanian locationsSpreadsheetText matchTonesUIProvideruseClipboarduseConsentuseControllableStateuseCooldownuseDebounceuseKeyboardInsetuseLocaleuseLongPressuseMediaControlsuseMediaQueryuseOverflowItemsusePersistedStateuseScrollEdgesuseScrollStateuseSelectionuseShortcutuseStickToBottom
GalleryTheme

AI Kit

Tool Call Timeline

AI Kit

Tool Call Timeline React component for Tailwind CSS v4

Suggestion ChipsUsage Meter
Live props
Appearance
variant
size
tone
color
codeAccent
Content
title
showToolName
showDurations
showInput
showOutput
Layout
codeMaxHeight240px
State
defaultOpen
Behavior
autoOpen
expandErrors
locale
Code
import { ToolCallTimeline } from "@/components/ui/tool-call-timeline"

<ToolCallTimeline />
  1. Home
  2. Components
  3. AI Kit
  4. Tool Call Timeline
Pro

Tool Call Timeline React component for Tailwind CSS v4

v1.0.0·Added in 1.0.0

A React tool call timeline for AI agents: each step with its status, time, input and output, plus approval and retry when a call needs them.

Each call is a row: a round marker says its status (a dashed ring while queued, a spinner while it runs, a check that pops once when it finishes, a cross when it fails, a hand that pings while it waits for a person), then a human title, the tool's id in a small mono chip and how long it took. A running call's title shimmers and its time ticks in tenths of a second. Click or tap a row, or press Enter or Space on it, to open its input and output as highlighted JSON (text results wrap), its error and its logs; long blocks scroll inside themselves and every block has a copy button. A call that waits for approval shows Reject and Approve; a failed one opens by itself and shows Retry; a button whose handler returns a promise spins until it settles, and focus moves back to the row when the buttons go away. Sub-steps sit indented under their step. The card variant adds a header with the run's state (a spinner, or Needs approval, Failed, Done in words; a hand or an alert in its icon tile when a person is needed or a call failed, which alone carries it in a card narrower than 448px), its progress while it runs (2 of 5 done) and total time, and a button that opens or closes every row at once; the inline variant is a one-line summary (Used 4 tools, 2.8 s) that opens by itself while a call runs or waits for approval and closes again 1.2 s after everything finished, unless you opened it yourself or focus is inside it (you just approved a call), so focus never drops to the page. Status changes are announced once each to screen readers. Rows lay out by their own width, so a timeline in a chat column or a side panel fits: when a row is narrow the tool id moves under the title and Approve and Reject share the width; on a phone they are 44px tall, rows have 44px targets and code blocks scroll sideways inside themselves. Reduced motion swaps the springs for quick fades and stops the shimmer and the ping.

Tool Call Timeline is a Pro React component in the React AI components category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add tool-call-timeline, together with Badge, Button, Code Block, Copy Button, Spinner and 10 more and the npm packages motion and lucide-react.

Add to a project

Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup

npx wingo-ui@latest add tool-call-timeline

Tool Call Timeline is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans

Usage

Import ToolCallTimeline from @/components/ui/tool-call-timeline.

import { ToolCallTimeline, type ToolCall } from "@/components/ui/tool-call-timeline"

export function AgentRun({
  calls,
  onApprove,
  onReject,
}: {
  calls: ToolCall[]
  onApprove: (call: ToolCall) => Promise<void>
  onReject: (call: ToolCall) => void
}) {
  return (
    <ToolCallTimeline
      variant="card"
      title="Collections agent"
      calls={calls}
      onApprove={onApprove}
      onReject={onReject}
      locale="en-US"
    />
  )
}

// a call waiting for a person, as the model sent it
export const sendReminder: ToolCall = {
  id: "call-send",
  name: "send_email",
  title: "Sending the email",
  status: "awaiting-approval",
  input: { to: "adam.foster@techsolutions.com", subject: "Reminder for invoice #2026-0405" },
}

Props

  • calls*
    ToolCall[]

    The calls in order, in the ToolCall shape from lib/ai-chat: id, name, title, status, input, output, error, startedAt, endedAt, durationMs, logs and steps (sub-steps). Keep them immutable so only the call that changed re-renders.

  • variantdefault "timeline"
    "timeline" | "card" | "inline"

    timeline: markers on a rail, for an agent page. card: the timeline in a panel with a header (title, progress, total time and the run's state). inline: a one-line summary that opens into the timeline, for a chat message.

  • titledefault ""
    ReactNode

    The card's heading or the inline summary's text. Empty falls back to labels.summary (Used 4 tools). The card's second line shows the progress while the run goes on (2 of 5 done), then the summary, with the total time.

  • sizedefault "md"
    "sm" | "md"

    Titles 13 / 14px, rows 32 / 40px, markers 20 / 24px. Sub-steps always use sm. On touch screens md rows grow to 44px and sm rows keep their look with a 44px hit area.

  • tonedefault "neutral"
    "neutral" | "brand" | "success" | "warning" | "danger" | "info"

    Paints the Approve button, the card header's icon, the inline summary's spinner and the focus tint. Markers always use the status colors (running is info, done success, failed danger, waiting warning).

  • colordefault ""
    string

    Any CSS color; replaces the tone. Text on the Approve button turns black or white by lightness.

  • codeAccentdefault ""
    string

    A hex color the input and output blocks build their syntax colors from (the code block's accent). Empty keeps the code block's own.

  • showToolNamedefault true
    boolean

    The tool's id (search_invoices) in a mono chip next to the title; in a row narrower than 512px it sits under the title (sm rows hide it below 448px).

  • showDurationsdefault true
    boolean

    How long each call took (live while it runs, from startedAt) and the run's total in the card and inline summaries.

  • showInputdefault true
    boolean

    The arguments the model sent, in an opened row.

  • showOutputdefault true
    boolean

    What the tool returned, in an opened row.

  • codeMaxHeightdefault 240
    number

    Height in px an input or output block may reach before it scrolls inside itself. Copy always takes the whole value.

  • defaultOpendefault false
    boolean

    inline: start with the timeline open under the summary.

  • open
    boolean

    inline: controlled open state. autoOpen asks for changes through onOpenChange.

  • onOpenChange
    (open: boolean) => void

    inline: called when the summary is pressed and when autoOpen opens or closes it.

  • autoOpendefault true
    boolean

    inline: opens while a call runs or waits for approval and closes 1.2 s after everything finished, unless the person opened it themselves or focus is inside it.

  • expandErrorsdefault true
    boolean

    A failed call starts with its details open, and opens by itself when a running call fails.

  • expandedKeys
    string[]

    Controlled: the ids of the calls (and sub-steps) whose details are open.

  • defaultExpandedKeys
    string[]

    The calls whose details start open (failed calls are added when expandErrors is on).

  • onExpandedKeysChange
    (keys: string[]) => void

    Called with the next ids when a row is opened or closed, and when a call fails with expandErrors on.

  • onApprove
    (call: ToolCall) => (void | Promise<unknown>)

    Shows Approve on calls awaiting approval. Return a promise to keep the button spinning (and Reject disabled) until it settles; then set the call's status.

  • onReject
    (call: ToolCall) => (void | Promise<unknown>)

    Shows Reject next to Approve. Set the call to canceled, or back to the model, in the handler.

  • onRetry
    (call: ToolCall) => (void | Promise<unknown>)

    Shows Retry on failed calls, spinning while a returned promise is pending.

  • renderInput
    (call: ToolCall) => ReactNode

    Replaces the JSON view of a call's input (a map, a diff). Return undefined to keep the JSON, null to hide it.

  • renderOutput
    (call: ToolCall) => ReactNode

    Replaces the JSON view of a call's output, e.g. invoices as a small table. Return undefined to keep the JSON, null to hide it.

  • localedefault ""
    string

    Locale for durations (0.8 s in en-US, 0,8 s in de-DE) and counts. Empty uses UIProvider's, then the page's.

  • now
    Date | number

    A fixed clock for running durations, for screenshots and tests. Without it running calls tick on the shared ticker (lib/ai-chat).

  • emptyState
    ReactNode

    Replaces the No steps yet row shown while calls is empty.

  • labels
    Partial<ToolCallTimelineLabels>

    Every visible and spoken string: summary(count, formatted), progress(done, total, formattedDone, formattedTotal), running(title), input, output, error, logs, approve, reject, retry, showDetails, hideDetails, empty, status (one word per status, partial), announce(title, status), copy, copied. English defaults in DEFAULT_TOOL_CALL_TIMELINE_LABELS.

  • classNames
    Partial<Record<"summary" | "summaryIcon" | "summaryTitle" | "summaryMeta" | "list" | "item" | "rail" | "marker" | "header" | "title" | "name" | "duration" | "status" | "chevron" | "details" | "description" | "input" | "output" | "error" | "logs" | "approval" | "retry" | "steps" | "empty", string>>

    Extra classes for the inner parts; summary is the card header or the inline summary button.

  • className
    string

    Extra classes for the root, merged last.

Parts

  • ToolCallItem

    component

    One call as an <li> with its details, approval and sub-steps, for lists of your own: render it inside an <ol> and set last on the final one to end the rail. Props: { call: ToolCall; last?: boolean; expanded?: boolean; defaultExpanded?: boolean; onExpandedChange?; expandErrors?; showInput?; showOutput?; showToolName?; showDurations?; renderInput?; renderOutput?; codeMaxHeight?; codeAccent?; onApprove?; onReject?; onRetry?; size?; tone?; color?; now?; locale?; labels?; classNames? }.

  • ToolCallStatusMarker

    component

    The 20 / 24px round status marker on its own (agent steps, workflow node runs); decorative, so pair it with the status in words. Props: { status: ToolCallStatus; size?: "sm" | "md" }.

  • DEFAULT_TOOL_CALL_TIMELINE_LABELS

    constant

    The English strings, to spread and override. Type: ToolCallTimelineLabels.

Examples

Inline in a message

A one-line summary above the answer that opens while tools run and folds away 1.2 s after.

Failure and retry

The tax portal answers 503: the call opens with its error and logs, and Retry succeeds on the second try.

Approval in brand

A deal the agent wants to create waits for a person; Approve spins until its promise settles.

Nested steps

A report step that ran three sub-steps, replayed live.

Custom output

renderOutput turns the invoices into rows with dollar amounts.

Narrow side panel

size sm in a 320px card, with a pinned clock for a stable running time.

Queued plan in English

Default labels, color="#7C3AED" and pending steps that run one by one.

Dependencies

motionlucide-reactbadgebuttoncode-blockcopy-buttonspinnertooltipuse-controllable-stateuse-localeuse-stick-to-bottomai-chatmotionnumber-formatrelative-timetonesui-config

Files

  • components/ui/tool-call-timeline.tsx

FAQ

Is the React Tool Call Timeline component free?

The preview, props and docs are free; copying the source needs a Pro plan. See plans.

How do I install Tool Call Timeline?

Run npx wingo-ui@latest add tool-call-timeline. It also adds the Wingo UI items it builds on (Badge, Button, Code Block, Copy Button, Spinner and 10 more) and the npm packages motion and lucide-react. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/tool-call-timeline.

How does Tool Call Timeline behave on phones?

Rows lay out by their own width, so a timeline in a chat column or a side panel fits: when a row is narrow the tool id moves under the title and Approve and Reject share the width; on a phone they are 44px tall, rows have 44px targets and code blocks scroll sideways inside themselves.

See also

TimelineCode BlockStepsAI ChatlibReasoning IndicatorAgent Status Card

Used in

Agent Status CardChat MessageAI Chat Page

More React AI components

Usage MeterFluid OrbGrid RevealMatrix OrbWorkflow CanvasVoice Input
All 17 React AI components

Articles using this component

  • AI Agent Tool Call UI: Steps, Approvals and Errors

    Building UI with AI agents · Oct 16, 2026 · 11 min read

  • AI Elements Alternative: 5 React AI Chat Kits Compared

    Building UI with AI agents · Oct 16, 2026 · 11 min read

PreviousSuggestion ChipsNext Usage Meter
Northwind AssistantReminder for invoice #2026-0405

autoOpen: true · expandErrors: true · defaultOpen: false