Wants to refund €49 to the customer
- Read ticket #482109:39:42
- Found two charges of €49 on 2 Jan09:39:48
- Asked for approval to refund €4909:39:56
The inbox for a team of agents: every task in a column by state, with what it did, how long it has run and what it needs from you.
Wants to refund €49 to the customer
Tagging 38 new tickets
Found a race on the cart timer
Matching 212 invoices to payments
Starts after the triage
The queue refused the restart
Rotated 14 keys, nothing broke
# One-time setup (tokens + lib helpers)
npx koalaui-cli@latest init
# Activate your Pro license (once per machine)
npx koalaui-cli@latest login <key>
# Add this component (its dependencies come along)
npx koalaui-cli@latest add agent-task-boardThe board draws what you give it and fetches nothing. Keep your tasks in state, decide which column each one belongs to, and render a card for it there. When a task changes state, move it to its new column: the board finds it by its value and glides it across.
The preview is yours to explore. Its code comes with a Pro license, paid once and used in every project.
Have a license? Unlock it here
import {
AgentTaskBoard,
AgentTaskBoardColumn,
AgentTaskBoardCard,
AgentTaskBoardCardHeader,
AgentTaskBoardCardTitle,
AgentTaskBoardCardElapsed,
AgentTaskBoardCardSummary,
AgentTaskBoardCardMeta,
AgentTaskBoardCardAgent,
AgentTaskBoardCardCount,
AgentTaskBoardCardDetail,
AgentTaskBoardCardTrace,
AgentTaskBoardCardStep,
AgentTaskBoardCardActions,
AgentTaskBoardEmpty,
} from "@/components/ui/agent-task-board"Set layout="list" for a narrow pane: the same columns stack into groups and the cards become rows. The toggle is yours to place; the board only changes shape, and every card glides to its new spot when it does.
Wants to refund €49 to the customer
Tagging 38 new tickets
Found a race on the cart timer
Matching 212 invoices to payments
Starts after the triage
The queue refused the restart
Rotated 14 keys, nothing broke
A card opens in place to show its trace and the actions you offer. One card is open at a time; pass expanded and onExpandedChange to drive it yourself. The current step takes the card's state, so a task that needs you blinks where it stopped.
Wants to refund €49 to the customer
Found a race on the cart timer
A card carries one of five states, the same as Agent Monitor. Only a working task pings and only one that needs you blinks, so a column can hold mixed states and the eye still goes where it is needed.
Tagging 38 new tickets
Wants to refund €49 to the customer
Starts after the triage
Rotated 14 keys, nothing broke
The queue refused the restart
Give the board a height and each column scrolls on its own, with its edges fading into the column. On a narrow screen the columns scroll sideways inside the board, never the page.
Waiting on the order history
Drafted a reply
Drafted a reply
Waiting on the order history
Drafted a reply
Drafted a reply
Waiting on the order history
Drafted a reply
Drafted a reply
Nothing to review
Nothing finished yet
The board and the context every part reads. It owns which card is open, the shared clock and the glide of a card to its new place. Every part accepts className, merged last.
| Prop | Type | Default | Description |
|---|---|---|---|
| layout | "board" | "list" | "board" | Columns side by side, or one list grouped by state. The same parts render both, and cards glide between the two. |
| now | number | - | The current time in epoch milliseconds. Every AgentTaskBoardCardElapsed counts up to it, so tick it from your own clock or a simulated one. |
| expanded | string | null | - | The value of the open card, when you control it. |
| defaultExpanded | string | null | null | The card open on the first render. |
| onExpandedChange | (value: string | null) => void | - | A card opened, or the open one closed. |
| animated | boolean | true | Turns the glide between columns and the arrival of new cards off. |
| density | "comfortable" | "compact" | - | Column and card spacing. Reads DensityProvider when unset. |
| Data attribute | Description |
|---|---|
| data-layout | board or list. |
One state of the work, as a region named by its heading. Children are cards, or AgentTaskBoardEmpty.
| Prop | Type | Default | Description |
|---|---|---|---|
| status | "working" | "waiting" | "idle" | "done" | "failed" | - | Sets the dot and the default title. |
| title | ReactNode | - | Replaces the status label, for a column that holds more than one state. |
| count | number | - | Shown at the end of the heading. The digits roll when it changes. |
| Data attribute | Description |
|---|---|
| data-status | The column's status, when set. |
One task. It opens in place to show its AgentTaskBoardCardDetail, and it is focusable through its title.
| Prop | Type | Default | Description |
|---|---|---|---|
| value* | string | - | A stable id. It names the open card and lets a card that changes column glide to its new place. |
| status | "working" | "waiting" | "idle" | "done" | "failed" | "idle" | Drives the mark: a pinging dot, a blinking dot, a check or a warning. On the board the column already says the state, so only the check and the warning show. |
| statusLabel | string | - | The status as read by a screen reader. Use it to translate. |
| Data attribute | Description |
|---|---|
| data-status | The card's status. |
| data-state | open or closed. |
| data-value | The card's value. |
The task's name, and the button that opens the card. Its hit area covers the whole card. Render one per card.
One line on what the agent did or is doing. A string swaps in place when it changes.
A quiet row for the agent and the counts.
Who is doing the work. Children are the name.
| Prop | Type | Default | Description |
|---|---|---|---|
| mark | ReactNode | - | A 16px icon or Avatar before the name. |
One figure of what the task used, such as reads or tool calls. Children are the label.
| Prop | Type | Default | Description |
|---|---|---|---|
| value* | number | - | The figure, in tabular numerals that roll when it changes. |
How long the task has run. It never reads the system clock: it counts from since to until, this part's now, or the board's.
| Prop | Type | Default | Description |
|---|---|---|---|
| since* | number | - | Start time in epoch milliseconds. |
| until | number | - | Stops the count at this time, for a finished task. |
| now | number | - | Overrides the board's now for this card. |
| format | (ms: number) => ReactNode | formatAgentTaskBoardElapsed | Writes the duration. The default reads 45s, 4m 12s, 1h 05m. |
What shows when the card is open, usually a trace and actions. Built on Radix Collapsible.
The task's steps in order, on a thin rail. Scrolls past 14rem.
One step of the trace.
| Prop | Type | Default | Description |
|---|---|---|---|
| time | ReactNode | - | Shown at the end of the line, in tabular numerals. |
| current | boolean | false | The step the agent is on. Its dot takes the card's state and its text full ink. |
| failed | boolean | false | Marks the step as failed. |
| Data attribute | Description |
|---|---|
| data-current | Present on the current step. |
| data-failed | Present on a failed step. |
The buttons you offer for the task, such as approve, decline, retry or open. Buttons inside take the xs size.
What a column says when it has no cards: a dashed slot on the board, a line in the list.