Task tray

Pro

Work running in the background, as one pill: how many are running and how many need you. Opens to the list, needs-you first. Progress is shown only when the service knows the total; otherwise the task just says it's running. A task with lastHeardAt that has been silent past staleAfter, or whose host is offline, isn't counted as running: it says "No update since 10:42" or that its host is offline, and the pill counts it as not heard from.

Markdown

Preview

Install

With the Candor CLI

First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/task-tray

Brings in: agent-avatar, locale, popover, relative-time, run-heartbeat, status, status-dot, step-list, work, utils · npm: lucide-react@^1.67.0

Usage

TSX · The example above
"use client"

import type { BackgroundTask } from "@/lib/work"
import { TaskTray } from "@/components/task-tray"

const ago = (m: number) => new Date(Date.now() - m * 60_000).toISOString()

const tasks: BackgroundTask[] = [
  { id: "t1", title: "Add region to customers", status: "running", agent: { id: "a-dev", name: "Dev agent", role: "dev" }, progress: { done: 4, total: 6 }, startedAt: ago(3) },
  { id: "t2", title: "Drop partner_tier_old", status: "waiting", agent: { id: "a-orch", name: "Keel", role: "orchestrator" }, startedAt: ago(60 * 20), needs: "Waiting for another approver" },
  { id: "t3", title: "Audit API rate limits", status: "running", agent: { id: "a-qa", name: "QA agent", role: "qa" }, startedAt: ago(12) },
  // Silent for 9 minutes: not counted as running, it says when it was last heard from.
  { id: "t5", title: "Backfill order totals", status: "running", startedAt: ago(30), lastHeardAt: ago(9) },
  { id: "t4", title: "Explain the invoice retry job", status: "succeeded", startedAt: ago(40) },
]

export default function Example() {
  return <TaskTray tasks={tasks} onOpenTask={() => {}} />
}

<TaskTray>

PropTypeDefaultDescription
tasksrequiredBackgroundTask[]—The background tasks; with none, the tray renders nothing.
onOpenTask((id: string) => void) | undefined—Called with a task's id when it's clicked in the list.
staleAfternumber | undefinedSTALE_AFTERHow long a running task may be silent before it's no longer called running, in milliseconds. Defaults to two minutes.
classNamestring | undefined—Extra classes for the outer element.

Strings

The fixed words, in English by default. Change any of them under taskTray in <LocaleProvider strings={{ … }}>; the table is exported as taskTrayStrings.

KeyEnglish
running{count} running
notHeard{ one: "{count} not heard from", other: "{count} not heard from" }
startedCount{count} started
needsYou{ one: "{count} needs you", other: "{count} need you" }
allDoneAll done
backgroundWorkBackground work
progressStep {done} of {total}
statusRunningRunning
statusFinishedFinished
statusQueuedQueued
started{status} · started