Reminders for September's overdue invoices
Sending reminders (2 of 3)
AI Kit
Agent Status Card
v1.0.0Added in 1.0.0
A React AI agent status card: orb, name, status, current step, progress, elapsed time, steps, logs and the controls that matter right now.
The card shows the agent's orb (it thinks while the agent runs, listens while it waits for a person and rests otherwise; it only animates near the viewport and holds still under reduced motion), its name and task, and a status badge whose dot pings while it runs and which pops once with a check when a run finishes with every step green. Under it the current step shimmers while it runs, a progress bar glides from step to step (Step 3 of 5) and the elapsed time ticks every second. Only the controls that matter now appear: Pause and Stop while it runs, Resume and Stop while paused, Reject and Approve in an amber box when it waits for approval, Retry in a red box when it failed, View result in a green box when it finished. Stop asks first in a centered dialog (Escape or Keep running cancels). A handler that returns a promise spins its button and disables the others until it settles; a rejection is announced. The Steps and Logs toggles at the bottom open the step timeline and a monospace log that follows new lines until you scroll up inside it, and scroll with the keyboard once focused. The ⋯ button opens the agent's menu, a bottom sheet on phones. Tab reaches every control in order, Enter and Space press them, and each control's name includes the agent's name (Stop Collections agent). Status changes are announced once to screen readers. The compact variant keeps the orb, name, status, current step, progress and one primary action for grids; the row variant is a 64px list line with a progress ring that opens the agent on click, tap or Enter. Below 400px the orb sits above the text, buttons share the width and grow to 44px on touch, and logs cap at 40% of the screen height.
Agent Status Card 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 agent-status-card, together with Alert Dialog, Badge, Button, Dropdown Menu, Fluid Orb and 12 more and the npm packages motion and lucide-react.
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 agent-status-cardAgent Status Card 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
Import AgentStatusCard from @/components/ui/agent-status-card.
import { AlertDialogProvider } from "@/components/ui/alert-dialog"
import { AgentStatusCard, type ToolCall } from "@/components/ui/agent-status-card"
const steps: ToolCall[] = [
{ id: "s1", name: "search_invoices", title: "Finding overdue invoices", status: "complete", durationMs: 820 },
{ id: "s2", name: "get_client_contacts", title: "Getting the contact details", status: "complete", durationMs: 410 },
{ id: "s3", name: "send_reminders", title: "Sending reminders (2 of 3)", status: "running" },
{ id: "s4", name: "update_statuses", title: "Updating the statuses", status: "pending" },
{ id: "s5", name: "send_report", title: "Sending the report", status: "pending" },
]
export function CollectionsAgent({
onPause,
onStop,
}: {
onPause: () => Promise<void>
onStop: () => Promise<void>
}) {
return (
<>
<AlertDialogProvider />
<AgentStatusCard
name="Collections agent"
task="Reminders for September's overdue invoices"
status="running"
steps={steps}
startedAt={new Date(2026, 8, 24, 16, 38, 2)}
logs={[{ time: new Date(2026, 8, 24, 16, 38, 5), message: "Found 3 invoices, $22,775.95 in total" }]}
onPause={onPause}
onStop={onStop}
labels={{
status: { running: "Working", paused: "On hold", complete: "Done" },
stopTitle: (name) => `Stop ${name} now?`,
elapsed: (duration) => `Working for ${duration}`,
}}
/>
</>
)
}namedefault ""ReactNodeThe agent's name, also used in the controls' accessible names and the stop dialog. Empty shows labels.untitled.
taskdefault ""ReactNodeWhat it is doing this run, clamped to two lines with the full text in a tooltip title.
statusdefault "idle""idle" | "queued" | "running" | "paused" | "awaiting-approval" | "complete" | "error" | "canceled"The run's state. It picks the badge (AGENT_STATUS_TONES: running info, paused and awaiting warning, complete success, error danger, the rest neutral), the orb's mood, the box under the progress and which controls show. In the playground Idle plays the live run and any other value forces that state.
stepsToolCall[]The run's steps in the ToolCall shape from lib/ai-chat. The progress (done / total), Step 3 of 5 and the current step derive from them, and the Steps toggle shows them as a tool-call-timeline.
currentStepdefault ""ReactNodeOverrides the derived current step (the running or waiting step's title, the failed one, else the last finished one). It shimmers while the agent runs.
progressnumber | null0 to 1, clamped; null is an indeterminate bar. Undefined derives it from steps; with no steps it is indeterminate while running and hidden otherwise.
startedAtDate | string | numberWhen the run started; the elapsed time counts from here (live while running or waiting).
endedAtDate | string | numberWhen it ended: Finished in 1 min 48 s, or Stopped after 14 s for failed and stopped runs. Ignored without startedAt.
logs(AgentLogEntry | string)[]Log lines ({ id?, time?, level?: debug | info | warn | error, message } or plain strings). Passing an array (even empty) shows the Logs toggle with its count.
approval{ question: ReactNode; description?: ReactNode; approveLabel?: ReactNode; rejectLabel?: ReactNode }The question shown in the amber box while status is awaiting-approval, with Reject and Approve when their handlers are set.
resultReactNodeShown in a green box with a check when the status is complete.
errorReactNodeShown in a red box with an alert icon when the status is error.
variantdefault "card""card" | "compact" | "row"card: everything, for a detail page. compact: orb, name, status, current step, progress and one primary action, for a grid of agents. row: a 64px list line with a 32px orb, name and current step, a progress ring with the percent (hidden when the row is narrower than 384px), the badge and the menu.
visualdefault "matrix-orb""matrix-orb" | "fluid-orb" | "icon" | "none"matrix-orb: dots that think while running, listen while waiting and rest otherwise. fluid-orb: a WebGL blob that drifts while running and holds still otherwise. icon: a round Bot mark tinted by the status. Orbs only mount near the viewport.
orbColordefault ""stringA hex color for the orb. Empty follows the status tone (blue while running, green when done, red when failed, gray at rest).
sizedefault "md""sm" | "md"Card orb 56 / 72px and name 15 / 17px. Compact (48px orb) and row (32px) keep their sizes.
radiusdefault "lg""none" | "sm" | "md" | "lg"Corners of the card and compact surfaces: 0, 12, 16 or 24px.
tonedefault "neutral""neutral" | "brand" | "success" | "warning" | "danger" | "info"The progress fill and the solid buttons (Resume, Approve, Retry). Status colors stay semantic.
colordefault ""stringAny CSS color; replaces the tone.
shimmerdefault truebooleanThe moving highlight on the current step while it runs (off under reduced motion; turn it off for static stills).
showStepsdefault "toggle""toggle" | "always" | "never"Card only: the steps timeline behind a Steps toggle, always open under the controls, or not at all.
showLogsdefault truebooleanCard only: the Logs toggle (shown when logs is an array).
defaultStepsOpendefault falsebooleanStart with the steps timeline open.
stepsOpenbooleanControlled open state of the steps panel.
onStepsOpenChange(open: boolean) => voidCalled when the Steps toggle is pressed.
defaultLogsOpendefault falsebooleanStart with the logs open.
logsOpenbooleanControlled open state of the logs panel.
onLogsOpenChange(open: boolean) => voidCalled when the Logs toggle is pressed.
onPause() => (void | Promise<unknown>)Shows Pause while running. A returned promise keeps the button loading and the others disabled until it settles.
onResume() => (void | Promise<unknown>)Shows Resume (solid) while paused.
onStop() => (void | Promise<unknown>)Shows Stop while running, paused or queued; asks first when confirmStop is on.
onRetry() => (void | Promise<unknown>)Shows Retry when the run failed or was stopped.
onApprove() => (void | Promise<unknown>)Shows Approve in the approval box.
onReject() => (void | Promise<unknown>)Shows Reject in the approval box.
onOpen() => (void | Promise<unknown>)Shows View result when complete; in the row variant the whole row opens the agent.
menuMenuEntry[]The ⋯ menu's entries (dropdown-menu's shape): Edit agent, Duplicate, Run history, Delete. A bottom sheet below 768px.
confirmStopdefault truebooleanAsk in an alert dialog before onStop (through useConfirm, so mount AlertDialogProvider once).
localedefault ""stringLocale for durations (1 min 58 sec in en-US), percents and counts. Empty uses UIProvider's, then the page's.
nowDate | numberA fixed clock for the elapsed time (screenshots, tests, a paused run). Without it a running agent ticks on the shared ticker.
labelsPartial<AgentStatusCardLabels>Every visible and spoken string: status (one word per status, partial), untitled, pause, resume, stop, stopTitle(name), stopDescription, keepRunning, approve, reject, approvalNeeded, retry, viewResult, steps, logs, stepOf(index, total), elapsed(duration), finishedIn(duration), stoppedAfter(duration), pausedAfter(duration), noLogs, menu, cancel (the menu sheet's close button on phones), announce(name, status), actionFailed. English defaults in DEFAULT_AGENT_STATUS_CARD_LABELS.
stepsLabelsToolCallTimelineLabelsInputLabels for the steps timeline (its status words, Approve, Retry).
classNamesPartial<Record<"visual" | "header" | "name" | "task" | "status" | "menu" | "current" | "progress" | "progressLabel" | "elapsed" | "approval" | "result" | "error" | "controls" | "toggles" | "steps" | "logs", string>>Extra classes for the inner parts.
classNamestringExtra classes for the root article, merged last.
The log scroller alone: monospace lines with 16:38:05 times and warn / error tags, following new lines until the reader scrolls up. A focusable labelled region, not a live region. Props: { logs?: (AgentLogEntry | string)[]; label?: string; emptyText?: ReactNode; showTime?: boolean; follow?: boolean; classNames? }.
The status to tone map, for your own badges and dots. Type: Record<AgentStatus, Tone>.
The English strings, to spread and override. Type: AgentStatusCardLabels.
The agent stops and asks. Approve settles after a fake request and the run completes.
The four agents of Summit CRM: running, waiting, done in 1 min 48 s, failed with Retry.
The same agents as 64px rows in a list; tap a row to open it, the menu stays separate.
visual="fluid-orb" in a custom blue, with the steps always visible.
300 generated lines (mulberry32) plus a new one every 1.2 s, following the tail.
size sm with a result, size md paused in the brand tone.
The log scroller as its own part, for a run detail page.
The preview, props and docs are free; copying the source needs a Pro plan. See plans.
Run npx wingo-ui@latest add agent-status-card. It also adds the Wingo UI items it builds on (Alert Dialog, Badge, Button, Dropdown Menu, Fluid Orb and 12 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/agent-status-card.
The ⋯ button opens the agent's menu, a bottom sheet on phones.
Building UI with AI agents11 min read
Reminders for September's overdue invoices
Sending reminders (2 of 3)
Pause, stop or open the steps and logs while it runs.
control: idle (live run) · status: running · step: 3/5 · confirmStop: true · opened: 0