WebberUI

AI 任務計畫追蹤(React)

agent 計畫清單的 React 元件:步驟由資料驅動在待辦→執行中→完成/失敗/略過間流轉,含工具圖示 chip、巢狀子步驟與連接線、目前步驟呼吸脈動、完成率與總耗時;狀態切換用 AnimatePresence 換圖示,新步驟從下方滑入。

像 agent 產品裡的 todo 追蹤面板:把 steps 資料丟進來,每一步依 status 顯示待處理空圈、執行中旋轉圈(整列微光呼吸)、完成打勾彈入、失敗叉、略過虛線圈;標題旁有工具 chip(工具名自動對到內建 lucide 圖示,可用 toolIcons 覆寫)與耗時,有說明或子步驟的列可展開,子步驟縮排並以左側連接線串起。頂部顯示完成率 x/y、三段式細進度條(完成/失敗/略過)與總耗時。元件不跑任何計時器——狀態全部由資料決定,你的 agent 回報什麼就畫什麼;狀態變化用 AnimatePresence 換圖示,新增的步驟從下方滑入。

載入預覽⋯
npx shadcn@latest add https://webberui.com/r/ai-plan-steps.json

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

<AiPlanSteps />

安裝

npx shadcn@latest add https://webberui.com/r/ai-plan-steps.json

或在 components.json 設定 registries 後,改用 @webberui/ai-plan-steps 安裝。

使用

import { AiPlanSteps, type PlanStep } from "@/components/ui/ai-plan-steps";

const steps: PlanStep[] = [
  {
    id: "audit",
    title: "盤點現有登入流程",
    status: "done",
    tool: "read",
    durationMs: 1050,
    children: [
      { id: "audit-read", title: "讀取 auth/ 目錄", status: "done", tool: "read", durationMs: 640 },
      { id: "audit-grep", title: "標記重複的驗證邏輯", status: "done", tool: "grep", durationMs: 410 },
    ],
  },
  { id: "extract", title: "抽出共用的 validateCredentials()", status: "running", tool: "edit" },
  { id: "test", title: "執行單元測試", status: "pending", tool: "test" },
];

<AiPlanSteps
  steps={steps}
  title="任務計畫"
  onStepClick={(step) => console.log(step.id)}
/>

狀態流轉由你更新 steps 陣列驅動(例如 agent 每次回報就 setState 一次),元件只負責把差異畫成動畫。

Props

Prop型別預設值說明
stepsPlanStep[]步驟資料(含巢狀 children);狀態流轉完全由這份資料驅動
titlestring"任務計畫"頂部標題文字;空字串則不顯示標題
toolIconsRecord<string, PlanToolIcon>工具名 → 圖示對照,會覆蓋同名的內建對照(鍵請用小寫)
showProgressbooleantrue是否顯示頂部完成率(x/y)、細進度條與總耗時
collapsiblebooleantruedetail 或子步驟的列是否可點擊收合;false 時永遠攤開且不顯示箭頭
defaultCollapsedbooleanfalse非受控模式下,可收合的列一開始是否收合
expandedIdsstring[]受控的展開清單(step id 陣列);提供時展開狀態完全由外部管理
onExpandedChange(ids: string[]) => void展開清單變更時回呼,參數為變更後所有展開列的 id
onStepClick(step: PlanStep) => void點擊任一列時回呼(與收合互不影響)
compactbooleanfalse緊湊模式:較小的字級、間距與圖示,工具 chip 只留圖示
strikeDonebooleanfalse已完成的步驟標題是否加刪除線
labelsPartial<AiPlanStepsLabels>覆寫介面文字(狀態朗讀字樣、完成率字樣、空狀態等)
classNamestring透傳到最外層容器

PlanStep

欄位型別預設值說明
idstring唯一識別,用於 React key、展開狀態與 aria-controls;建議只含英數、-_
titlestring步驟標題
status"pending" | "running" | "done" | "failed" | "skipped"目前狀態
toolstring使用的工具名(如 readbash);對應到 toolIcons 的圖示並顯示為 chip
detailstring展開後顯示的補充說明(結果摘要、錯誤訊息等);失敗狀態以紅字顯示
durationMsnumber耗時(毫秒);提供時顯示於列尾並計入總耗時
childrenPlanStep[]子步驟;有子步驟或 detail 的列會出現展開箭頭

AiPlanStepsLabels

欄位型別預設值說明
pendingstring"待處理"待處理狀態的朗讀文字
runningstring"執行中"執行中狀態的朗讀文字,也用於即時區域的「執行中:…」
donestring"完成"完成狀態的朗讀文字
failedstring"失敗"失敗狀態的朗讀文字
skippedstring"略過"略過狀態的朗讀文字
progressstring"已完成"完成率數字後的字樣
totalDurationstring"總耗時"總耗時的無障礙標籤
emptystring"尚無步驟"沒有任何步驟時顯示的文字

另外具名匯出 summarizePlanSteps(steps)(回傳扁平化後各狀態數量與總耗時)、formatPlanDuration(ms)820ms / 1.4s / 12s / 1m 05s),以及 PlanStepPlanStepStatusPlanToolIconPlanSummaryAiPlanStepsLabelsAiPlanStepsProps 型別。

細節

  • 內建工具圖示對照readwriteeditsearchgrepglobbashshellterminalwebfetchbrowsedbdatabasesqlgittestbuilddeploycodethinkplan。查找時先比對整個小寫名稱,再用「包含關鍵字」比對(read_filereadweb_searchsearch,長鍵優先),都沒中就顯示扳手圖示;用 toolIcons 傳入自己的對照即可覆寫或新增
  • 完成率與總耗時:數量以整棵樹扁平化後計算(含所有層級的子步驟);總耗時則是父步驟自己有 durationMs 就以父為準,沒有才加總子步驟,避免父子重複計算
  • 展開狀態:非受控模式只記錄使用者動過的列,其餘依 defaultCollapsed 推定,因此事後新增的步驟也套用同一個預設;需要記憶或同步時改用 expandedIds + onExpandedChange 受控
  • 動畫:狀態圖示以 AnimatePresence popLayout 換場(完成打勾用 spring 彈入)、執行中列疊一層淡藍底做呼吸、進度條寬度平滑過渡、新列以 layout 位置動畫從下方滑入、移除的列淡出後由其餘列補位;元件本身沒有任何 setTimeout/setInterval

可及性

  • 最外層為 section 並以標題 aria-labelledby;清單用 role="list"role="listitem"(Safari 對 list-style: none 的清單會拿掉語意,明確標註才保得住),執行中的列加 aria-current="step"
  • 可收合的列是原生 buttontype="button"),帶 aria-expandedaria-controls 指向說明區;鍵盤 Tab/Enter/Space 可操作,focus-visible 有 ring
  • 每列標題後附僅供螢幕閱讀器的狀態文字(「(執行中)」等,可用 labels 換語言);頂部另有 role="status"aria-live="polite" 摘要,完成率或執行中步驟變化時會被朗讀
  • 進度條為 role="progressbar"aria-valuenow 為完成數、aria-valuemax 為總步驟數
  • 使用者系統開啟「減少動態效果」時,停用旋轉、呼吸、彈入、滑入與 layout 位移動畫,狀態切換只保留淡入淡出與顏色變化

本頁目錄