Mischief

24 / Agent UI

Agent Checklist

A task list whose items change state as work proceeds, announcing what changed instead of re-reading the whole list.

Fixing the migration

0/4
  1. Read the migration, in progress
  2. Check the column constraints, waiting
  3. Reorder the statements, waiting
  4. Run the test suite, waiting

Installation

Copy the source into your project, or keep it behind a package.

npx shadcn@latest add Tinkerers-Labs/mischief-ui/agent-checklist
import { AgentChecklist } from "mischief-ui/agent-checklist"
Also installs
  • lucide-react

Or paste it in yourself. The source imports the shared cn helper from @/lib/utils, so point that at your own copy.

registry/default/agent-checklist/agent-checklist.tsx
"use client" import * as React from "react"import { Check, Circle, Loader, Minus, TriangleAlert } from "lucide-react"import { cn } from "@/lib/utils" export type ChecklistItemStatus =  "pending" | "active" | "done" | "error" | "skipped" export type AgentChecklistItem = {  id: string  label: React.ReactNode  status: ChecklistItemStatus  detail?: React.ReactNode

Usage

const items = [
  { id: "read", label: "Read the changelog", status: "done" },
  { id: "diff", label: "Compare versions", status: "active" },
  { id: "write", label: "Draft the summary", status: "pending" },
]

export function Plan() {
  return <AgentChecklist items={items} title="Plan" />
}

The five states

Every item is in exactly one state, and the wording each maps to is what a screen reader hears alongside the label.

StatusRead as
pendingwaiting
activein progress
donedone
errorfailed
skippedskipped

skipped exists so a plan that changed does not have to lie. An agent that decided a step was unnecessary should mark it skipped rather than done, which is the difference between a truthful record and a tidy one.

Announcing progress

With announce on, each change is read out as it happens. That is genuinely helpful for a plan of five or six steps and unbearable for a plan of forty, so turn it off for long lists and let the progress count carry the story instead.

Write labels as the thing being done, short enough to be heard in one breath: Reading the invoice, not Now attempting to read the uploaded invoice document. Detail is for detail.

<AgentChecklist
  title="Extracting the invoice"
  items={[
    { id: "read", label: "Reading the file", status: "done" },
    { id: "fields", label: "Finding the fields", status: "active" },
    { id: "verify", label: "Checking the totals", status: "pending" },
  ]}
/>

API

itemsAgentChecklistItem[]Id, label, status, and optional detail per step. Fully controlled.
titleReactNodeAn optional heading above the list.
announcebooleanAnnounces status transitions politely. Defaults to true.
showProgressbooleanShows the settled count in the header. Defaults to true.

AgentChecklistItem

idstringUnique within the list.
labelReactNodeThe step, phrased as the thing being done.
statusChecklistItemStatuspending, active, done, error, or skipped.
detailReactNodeA second line, for what the step actually found.

Accessibility

The list is an ordered list and every item states its status in text for screen readers, not through colour or icon alone. When a status changes, only the difference is announced along with a running count, so a long list does not get re-read on every update. Spinners stop under reduced motion.