Components
AgentStatus
The run’s state in one pill, announced to screen readers.
Example
Interactive, and the same on the components page. Try the keyboard below on it.
Installation
npm i @dgesteves/agent-ui-kit aiimport { AgentStatus, deriveAgentState } from '@dgesteves/agent-ui-kit';
// Once per app (with Tailwind v4: @import '@dgesteves/agent-ui-kit/tailwind.css'; in your CSS)
import '@dgesteves/agent-ui-kit/styles.css';npx shadcn@latest add @agent-ui-kit/agent-statusimport { AgentStatus } from '@/components/agent-ui/agent-status';
import { deriveAgentState } from '@/components/agent-ui/lib/ai';The styles are once per app; Getting started has the Tailwind v4 and plain CSS options.
Usage
const last = messages.findLast((m) => m.role === 'assistant');
// Waiting on a person (an approval, a client-side tool) wins over "working".
const { state, detail } = deriveAgentState({ status, message: last, pendingClientTools: ['review_changes'] });
<AgentStatus state={state} detail={detail} />API reference
Generated from the types the package ships, so it matches the version you install.
AgentStatus
A compact, live status pill for an agent run. State changes are announced through a polite live region (assertive for errors and approval requests), debounced so rapid transitions do not flood screen readers.
Props
staterequiredAgentState'idle' | 'thinking' | 'working' | 'awaiting-approval' | 'done' | 'error'labelstringOverrides the default label for the state.
detailstringSecondary detail, e.g. the tool being run.
startedAtnumberEpoch ms when the run started. Shows a live elapsed timer while active.
elapsedMsnumberFixed elapsed time to show (e.g. the final run duration). Takes precedence over
startedAt.announcebooleanDefaulttrueAnnounce state changes to assistive tech.
size'sm' | 'md'Default'md'
Other props go to the root <div>: className (merged with tailwind-merge), id, aria-*, data-* and event handlers.
AgentState
type AgentState = 'idle' | 'thinking' | 'working' | 'awaiting-approval' | 'done' | 'error';Accessibility
- Changes are announced through a live region, debounced by 350 ms so quick flips aren’t read one by one. Approvals and errors are assertive; everything else is polite.
- Render one
AgentStatusper run withannounceon; passannounce={false}to any copy, or the state is read twice. - Each state has an icon and a word. The thinking shimmer and the spinner run only without
prefers-reduced-motion.
Theming
Every color, radius and font is a CSS variable, so the overrides in Theming apply, on :root or scoped to any element. These hooks are read from the component's markup.
- Slots (data-slot)
- agent-status
- State attributes
- data-stateon
agent-status'idle' | 'thinking' | 'working' | 'awaiting-approval' | 'done' | 'error' - Tokens it uses
- --aui-accent--aui-accent-fg--aui-border--aui-fg--aui-fg-muted--aui-fg-subtle--aui-font-mono--aui-font-sans--aui-hot--aui-hot-fg--aui-surface
/* Only this component, and only inside .settings-panel */
.settings-panel [data-slot='agent-status'] {
--aui-radius: 4px;
}
[data-slot='agent-status'][data-state='idle'] {
outline: 1px solid var(--aui-accent);
}