Task Tree
Shows the tasks of a run and how they break into parts. A task with one part continues straight down; a task with several branches them out. Each row has a Status mark, so the tree updates as your app changes task states. For a saved plan with criteria and dependencies, use Plan Outline. For agents that start other agents, use Agent Fanout.
Live run
Two tasks run at a time. A parent’s mark follows its parts: it fills as they finish, and fails if one fails. Lines turn green as the tasks they lead to succeed.
Tasks
0 of 6 done- Scaffolding project
- Installing dependencies
- Defining signups schema
- Implementing join logic
- Adding SQLite layer
- Wiring POST /api/join
- Building join API
- Handling UI states
- Building landing form
- Smoke testing API
- Building join API
- Writing unit tests
- Testing
- Wiring POST /api/join
- Adding SQLite layer
- Implementing join logic
- Validating email input
- Building signup form
- Defining signups schema
- Ignoring DB files
- Writing README
- Installing dependencies
Every state
Parents without a state follow their parts, so one failed upload marks the release failed. “Announcing” sets its own state. Long titles wrap under themselves.
Release
2 of 5 done- Releasing v2.4
- Drafting release notes from 38 merged pull requests and the changelog entries they reference12s
- Publishing packages
- PyPI60%
- npmWaiting for 2FA
- Docker imageRegistry timed out
- Announcing in #releases
- Posting to social
No tasks
Before the first task arrives, the tree says so.
Tasks
No tasks yet. They appear here as the agent plans.
Usage
import { TaskTree } from "@tulipfarm/sprout/task-tree";
<TaskTree
tasks={[
{
id: "scaffold",
title: "Scaffolding project",
state: "success",
children: [
{ id: "deps", title: "Installing dependencies", state: "running", value: 40, detail: "40%" },
{ id: "ignore", title: "Ignoring DB files", state: "success", children: [
{ id: "readme", title: "Writing README", state: "pending" },
] },
],
},
]}
/>tasks:{ id, title, state?, value?, detail?, children? }.stateandvaluego to Status.detailis short muted text at the end of the row, such as a duration or a count.children: the task's parts. One part stays in the same column with a straight line. Two or more move one column in, each with its own branch.- A task with parts and no
statefollows them: failed if any part failed, running if any is running, succeeded once all have finished. While running, its ring fills with the share of parts done. Setstateto override it. title: the heading, “Tasks” by default.summaryreplaces the “3 of 8 done” count; passnullto hide it. The count covers tasks without parts. Succeeded, warning, and skipped tasks count as done.empty: shown when there are no tasks. Defaults to “No tasks yet.”
Lines are drawn with React Flow at a fixed 24px column and 32px row, with panning, zoom, and selection turned off. Long titles end in an ellipsis.
Motion
When a task succeeds, a green line grows from it up to its parent over 280ms. A parent that follows its parts changes only once that line arrives, so the green climbs the tree one level at a time. Other changes show at once. Rows added later fade in over 220ms. The server sends a static drawing of the same tree, which React Flow replaces in place without replaying anything. With reduced motion, lines turn green at once and rows only fade.
Accessibility
The section is named by its heading. Screen readers get the tasks as nested lists, with each Status mark named after its state, such as “Running, 40%”; the drawing is hidden from them. The done count is a polite live region, so progress is announced as tasks finish.
Theme tokens
Lines use --sprout-muted mixed 40% into --sprout-surface, and --sprout-success once the task below them has succeeded. Pending and skipped titles use --sprout-muted. In forced colors, lines use GrayText and finished lines CanvasText.