Task List
betaThe agent's plan as a todo list: segmented progress, shimmering current task, live and final durations, failure details, sub-tasks and a folded Completed group.
A plan in progress
- Read routes in src/app (done)21.4s
- Map call sites of fetchUser() (done)48.2s
- Patch src/auth/client.ts (in progress)
- Run pnpm test (pending)
Live run
The auth-client migration plays out: finished tasks fold into Completed, sub-tasks tick, the test run fails, a fix task appears, the re-run passes, the reviewer signs off and the PR opens.
Every state
Done, skipped, waiting for approval, failed with a reason, paused and queued.
- Bump version to 2.4.0 (done)3.2s
- Regenerate API types (skipped)Schema unchanged since 2.3.1
- Run database migration 0042_sessions (waiting for you)Needs your approval — touches production
- Build preview deployment (failed)next build exited with code 1 — Type error in src/middleware.ts:311m 24s
- Notify #releases (paused)
- Tag release (pending)
Plan beside output
The plain variant in a sidebar; selecting a task shows its output on the right.
$ pnpm test ✕ login.test.ts › refreshes an expired session expected 200, received 401 141 passed, 1 failed (38.4s)
Installation
npx shadcn@latest add https://kuro.abstergo.fyi/r/task-list.jsonCopies the source into components/kura/task-list with its dependencies (kura-theme, kura-format, shimmer-text, status-glyph, use-controllable-state, use-elapsed, utils). Tokens come from the kura-theme item.
When to use it
Use it for
- Show the todo list a coding agent maintains while it works (Claude Code TodoWrite, Codex plan, Cursor tasks) in a run sidebar or panel.
- Give a dense, scannable answer to 'what is the agent doing and what is left?' — '3 of 7' plus one row per task.
- Let the user click a task to show its output or diff next to the list (`onSelect` + `selectedId`).
- Show a failed task with its reason (`detail`) and a task blocked on the human (`waiting`).
Reach for something else when
- A narrative step timeline with connectors and inline tool calls under each step — use agent-timeline.
- Parallel subagents working at the same time — use agent-fleet.
- Timing analysis of nested spans on a shared time axis — use trace-waterfall.
- A single tool invocation with arguments and result — use tool-call.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| items* | readonly TaskListItem[] | — | The plan, in order. TaskListItem = { id, title, status: "queued" | "running" | "waiting" | "done" | "failed" | "skipped" | "paused", detail?, durationMs?, startedAt?, children? }. |
| title | React.ReactNode | "Plan" | Heading in the panel header (panel variant only). |
| actions | React.ReactNode | — | Controls on the right of the header, after the progress bar (e.g. an IconButton). |
| variant | "panel" | "plain" | "panel" | panel = card with header, '3 of 7' and segmented progress; plain = rows only, for embedding in your own sidebar. |
| collapseCompleted | boolean | true | Fold the leading run of finished (done/skipped) items into a 'Completed (n)' row while work remains. Needs at least three finished items; a fully finished plan is shown in full. |
| completedOpen | boolean | — | Whether the Completed group is expanded (controlled). |
| defaultCompletedOpen | boolean | false | Initial expanded state of the Completed group when uncontrolled. |
| onCompletedOpenChange | (open: boolean) => void | — | Called when the Completed group is toggled. |
| selectedId | string | null | — | Highlighted item (bg-kura-active plus a 2px accent bar). Purely visual; pair with onSelect. |
| onSelect | (id: string, item: TaskListItem) => void | — | Makes rows buttons (with Up/Down/Home/End navigation) and reports the clicked item. Without it rows are static. |
| empty | React.ReactNode | — | Content when `items` is empty. Default: a quiet 'No plan yet' state. |
| label | string | — | Accessible name of the list. Default: `title` when it is a string, else 'Plan'. |
All native attributes of the root element, className and ref pass through.
Anatomy
- TaskListRoot. `data-variant`, `data-progress="done/total"`; contains a polite status region.
data-slot="task-list" - Headerh-10 header: title, mono 'n of m', segmented progress, actions.
data-slot="task-list-header" - ProgressOne 4px segment per top-level item, coloured by status (neutral done, blue running, amber waiting, red failed).
data-slot="task-list-progress" - CompletedThe folded group of finished items. `data-state="open" | "closed"`; its button has aria-expanded.
data-slot="task-list-completed" - Item<li> with `data-status` and `data-selected`; the running item has aria-current="step".
data-slot="task-list-item" - RowThe row: StatusGlyph, title, detail, duration. A <button> when onSelect is set.
data-slot="task-list-row" - TitleShimmers while running; muted when done; struck through when skipped. Status is spoken after it.
data-slot="task-list-title" - DetailSecond line. Red for failed, amber for waiting, subtle otherwise.
data-slot="task-list-detail" - DurationMono, tabular, width-reserved. Live clock (0:42) while running, final duration (1m 12s) after.
data-slot="task-list-duration" - ChildrenNested <ul> of sub-tasks with a hairline guide; the parent shows 'done/total'.
data-slot="task-list-children" - EmptyRendered when there are no items.
data-slot="task-list-empty"
Accessibility
- Role:
list - A <ul> labelled by `label`/`title`; each item speaks its status after the title (“Run pnpm test (failed)”), and the running item has aria-current="step".
- A polite status region announces the current task (“Task 4 of 7: Patch src/middleware.ts”), a failure, “Waiting for you” or “All tasks complete”. Live timers are never announced.
- With onSelect, rows are buttons with aria-pressed reflecting selectedId; the Completed toggle has aria-expanded/aria-controls.
- Status is never colour-only: the glyph shape and the spoken status carry it.
- Reduced motion: Rows fade in without rising, the title shimmer and running segment pulse stop, and the chevron turns without animating.
| Keys | Action |
|---|---|
| Tab | Moves into the list (rows are buttons when onSelect is set). |
| ArrowDown / ArrowUp | Moves focus to the next / previous row. |
| Home / End | Moves focus to the first / last row. |
| Enter / Space | Selects the focused task, or toggles the Completed group. |
Notes for agents
- Map a model-maintained todo list directly: pending → queued, in_progress → running, completed → done. Keep ids stable so rows don't remount.
- Pass `startedAt` for the running item (from your server) so the live timer survives reloads; pass `durationMs` once it finishes.
- Only one top-level item should be `running`; it carries the blue signal and the shimmer.
- Use `waiting` (amber) only when the agent is blocked on the human, and put the ask in `detail`.
- The Completed fold only collapses the *leading* finished items, so a failed task in the middle is never hidden.