Objectives
React 任务目标追踪组件:深色横条上方为斜体标题,每个目标前带一个斜切标记,已完成的目标以删除线标出。
安装
# once per project: where @zzzui items come frompnpm dlx shadcn@latest registry add @zzzui=https://zzzui.catforest.dev/r/{name}.jsonpnpm dlx shadcn@latest add @zzzui/objectives示例
班次任务目标
Night shift
Done: Reach the rail yards
Current: Load the sealed crates2 / 5
To do: Cross the river before the gate shuts
To do: Hand over at the North gate
import { useState } from "react";import { Button } from "@/components/zero/button";import { Objective, ObjectiveCount, ObjectiveDescription, type ObjectiveState, Objectives, ObjectivesHeader, ObjectiveTitle,} from "@/components/zero/objectives";const steps = [ "Reach the rail yards", "Load the sealed crates", "Cross the river before the gate shuts", "Hand over at the North gate",];export default function ObjectivesShift() { const [step, setStep] = useState(1); const [crates, setCrates] = useState(2); const [failed, setFailed] = useState(false); const state = (index: number): ObjectiveState => index < step ? "done" : index === step ? failed ? "failed" : "active" : "pending"; const advance = () => { if (step === 1 && crates < 5) setCrates((n) => n + 1); else setStep((s) => Math.min(steps.length, s + 1)); }; return ( <div className="grid justify-items-start gap-5"> <Objectives aria-label="Night shift"> <ObjectivesHeader>Night shift</ObjectivesHeader> {steps.map((title, index) => ( <Objective key={title} state={state(index)}> <ObjectiveTitle>{title}</ObjectiveTitle> {index === 1 ? <ObjectiveCount>{crates} / 5</ObjectiveCount> : null} {index === 2 && state(index) === "active" ? ( <ObjectiveDescription> The gate shuts at 02:00. </ObjectiveDescription> ) : null} </Objective> ))} </Objectives> <div className="flex flex-wrap gap-3"> <Button size="sm" onClick={advance} disabled={failed}> Next </Button> <Button variant="danger" size="sm" onClick={() => setFailed(true)} disabled={failed || step >= steps.length} > Fail it </Button> <Button variant="ghost" size="sm" onClick={() => { setStep(1); setCrates(2); setFailed(false); }} > Start over </Button> </div> </div> );}行为
每个目标前有一个斜切标记:未开始时为空框,进行中为强调色边框,完成时填满强调色并带对勾,失败时为红色并带叉号。已完成或已失败的目标,标题会从左端开始画出一道删除线。背后的横条向右渐隐,因此可以叠放在地图或场景之上。
状态也会以文字告知读屏软件(「Done:」「Current:」)。ObjectiveCount 位于该行末尾;ObjectiveDescription 位于标题下方。
属性
Objective
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| state | "pending" | "active" | "done" | "failed" | "pending" | 标记样式,以及标题的绘制方式。 |
| labels | Partial<Record<ObjectiveState, string>> | objectiveLabels | 读屏软件在标题前读出的状态说明(如 "Done: "),按状态分别设定。 |