affectUI › Components › Agents

Fan-out Grid

One agent hands a big job to many workers – every task a cell on a live grid that fills in as they get through it, with retries, failures, cost and the time left, and the details of any task on hover.

Part of affectUI Pro. Install: npx shadcn@latest add https://www.affectui.com/r/fan-out-grid.json · Import from @/components/ui/fan-out-grid

When to use

  • An agent fans one job out to many workers – enriching leads, translating pages, labelling tickets, running evals – and you want to watch it fill in
  • Batch runs with hundreds of tasks, where retries and failures matter more than any single step
  • A live overview next to a run's log: how far it is, what it costs, how long is left

When not to use

  • A handful of agents and who started whom – use Agent Tree
  • Where the time of one run goes, step by step – use Trace Waterfall
  • Several agents side by side over time – use Agent Lanes

Usage

import { FanoutGrid, type FanoutTask } from "@/components/ui/fan-out-grid";

const tasks: FanoutTask[] = leads.map((lead) => ({
  id: lead.id,
  label: lead.domain,
  status: lead.status, // "queued" | "running" | "retrying" | "done" | "failed"
  worker: lead.worker,
  start: lead.startedMs, end: lead.endedMs,
  cost: lead.cost, attempts: lead.attempts,
  result: lead.summary, error: lead.error,
}));

export function Enrichment({ elapsed }: { elapsed: number }) {
  return <FanoutGrid tasks={tasks} job="Enrich 240 leads" workers={16} now={elapsed} onRetry={(ids) => retry(ids)} />;
}

Props

NameTypeDefaultDescription
tasksFanoutTask[]{ id, label, status, worker?, start?, end?, cost?, attempts?, result?, error? } – one per task, in the order the cells should show
status"queued" | "running" | "retrying" | "done" | "failed"Per task – picks the cell's tint: gray, blue with a shine, amber, green, red
start / endnumberPer task, in ms from the start of the job – used for its duration and the time left
attemptsnumberPer task – 2 and more show in its details
jobstringWhat the whole job does, next to the title – e.g. "Enrich 240 leads"
workersnumberHow many workers run at once – the time left is worked out from it (defaults to the tasks running now)
nownumber0The clock, in ms from the start of the job
onRetry(ids: string[]) => voidShows "Retry failed" while tasks have failed, and gets their ids
onSelect(task | null) => voidA task was picked (click or Enter) – null when it's let go
formatCost(amount: number) => stringdollarsFormats every cost
titlestring"Fan-out"Heading of the bar
iconReactNodeA small mark before the title, e.g. the agent's logo
classNamestringExtra class on the root

Keyboard

  • Tab: Moves into the grid (one stop) and on to the counts on the tray and Retry
  • ArrowLeft / ArrowRight / ArrowUp / ArrowDown: Walks the cells and shows each one's details; Home and End jump to the first and the last
  • Enter / Space: Keeps the details open, or lets them go
  • Esc: Lets go of the details

Accessibility

  • The grid is a single tab stop; the details of the cell you're on are its description
  • The counts on the tray under the card are toggle buttons (aria-pressed) that show only one state
  • The run's progress is announced politely in steps of ten percent, and once more when it's finished

Responsive

  • Built on a container query: the grid fills whatever width it gets, the cells wrap into rows
  • Under 520px the cells get smaller and the numbers move to a line of their own
  • Dark mode built in: switches when an ancestor (usually <html>) has the class dark or data-theme="dark"

Requirements

  • React 19

Related

  • Agent Tree – Who started whom – an orchestrator and its sub-agents as a live tree, with status, cost and time on every card, costs rolling up each branch, and branches that fold to one line
  • Trace Waterfall – Where the time and money of an agent run go – every LLM call, tool call and sub-agent as a bar on a live timeline, with tokens and cost per step, the slowest call marked and branches that fold into their parent
  • Agent Lanes – Where every agent is right now – a live timeline with a lane per agent, tasks growing into “now”, hand-offs drawn between agents and approvals right on the block
  • Agent Queue – The work waiting for your agents, and how fast it moves – jobs drop into a live queue, glide into free worker slots as growing bars and land in Done or Failed, while a depth chart shows the backlog build up when a rate limit pauses the workers and drain when they resume

Guides