why-agent / client /frontend /src /components /PhaseTimeline.tsx
MapoTofu9's picture
deploy: HF Spaces
5d30bdc
Raw
History Blame Contribute Delete
3.56 kB
"use client";
import type { Phase } from "@/lib/types";
const PHASES: Phase[] = ["plan", "decompose", "drill", "cross_check", "critique", "report"];
const LABELS: Record<Phase, string> = {
plan: "Plan", decompose: "Decompose", drill: "Drill",
cross_check: "X-Check", critique: "Critique", report: "Report",
};
const DESCRIPTIONS: Record<Phase, string> = {
plan: "Frame the question and choose the first checks.",
decompose: "Break the metric into likely drivers and segments.",
drill: "Investigate the strongest candidate causes in detail.",
cross_check: "Verify the explanation against alternate slices.",
critique: "Check whether the evidence is strong enough.",
report: "Summarize the answer, evidence, and next steps.",
};
interface Props { currentPhase: Phase | null; completedPhases: Phase[]; }
export default function PhaseTimeline({ currentPhase, completedPhases }: Props) {
return (
<div className={`flex w-full items-start pt-2 ${currentPhase ? "pb-10" : "pb-2"}`}>
{PHASES.map((phase, i) => {
const isDone = completedPhases.includes(phase) && phase !== currentPhase;
const isActive = phase === currentPhase;
const tooltipAlign =
i === 0
? "left-0"
: i === PHASES.length - 1
? "right-0"
: "left-1/2 -translate-x-1/2";
return (
<div key={phase} className="flex flex-1 items-start last:flex-none">
<div className="relative flex flex-col items-center gap-1.5">
<div className={`w-3 h-3 rounded-full transition-all duration-500 ${
isActive ? "bg-violet-400 animate-glow scale-110"
: isDone ? "bg-violet-400"
: "bg-frame"
}`} />
<span className={`flex items-center gap-1 text-[10px] font-mono whitespace-nowrap transition-colors ${
isActive ? "text-violet-300 font-semibold"
: isDone ? "text-violet-400"
: "text-violet-700"
}`}>
{LABELS[phase]}
{currentPhase && (
<span className="relative group/info inline-flex">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
className="w-3 h-3 text-violet-600 group-hover/info:text-violet-300"
>
<path strokeLinecap="round" strokeLinejoin="round" d="M12 17v-5" />
<path strokeLinecap="round" strokeLinejoin="round" d="M12 8h.01" />
<path strokeLinecap="round" strokeLinejoin="round" d="M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
<span className={`pointer-events-none absolute top-full z-20 mt-1.5 hidden w-52 max-w-[min(13rem,calc(100vw-3rem))] whitespace-normal break-words rounded-md border border-frame bg-surface px-2.5 py-1.5 text-left text-[10px] font-mono leading-snug text-violet-200 shadow-xl group-hover/info:block ${tooltipAlign}`}>
{DESCRIPTIONS[phase]}
</span>
</span>
)}
</span>
</div>
{i < PHASES.length - 1 && (
<div className={`mx-4 mt-1.5 h-px flex-1 ${isDone ? "bg-violet-500" : "bg-frame"}`} />
)}
</div>
);
})}
</div>
);
}