mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-07 08:27:12 +00:00
run-stages: - replace the full-width tinted System/Assistant cards with a subtler left-accent bar and header so dense streams read cleanly - unify the Running/Timed out/exit/duration indicators under a shared StatusPill, and bump stdout/stderr labels from 10px to 11px - raise the selected stage header from text-sm font-medium to text-base font-semibold - command output preformatted text is now text-sm on mobile run-overview and run-graph: - extract the floating direction/fit/zoom controls into a single GraphToolbar capsule with internal dividers, shared between both graph views - drop the translucent canvas in favor of solid bg-panel-alt - wrap the "no workflow graph" message in a proper empty-state panel run-billing: - tfoot now uses bg-overlay so totals read heavier than the body - table headers gain font-medium and a readable fg-3 instead of fg-muted - "By model" heading is a real section heading, not an eyebrow - add an empty state when a run has no billing yet stage-sidebar: - cancelled stages now use NoSymbolIcon so they don't look identical to failed stages at a glance Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
84 lines
3 KiB
TypeScript
84 lines
3 KiB
TypeScript
import { ArrowDownIcon, ArrowRightIcon, MinusIcon, PlusIcon } from "@heroicons/react/20/solid";
|
|
|
|
type Direction = "LR" | "TB";
|
|
|
|
export const GRAPH_ZOOM_STEPS = [25, 50, 75, 100, 150, 200];
|
|
export const GRAPH_DEFAULT_ZOOM_INDEX = 2;
|
|
|
|
export function GraphToolbar({
|
|
direction,
|
|
setDirection,
|
|
fitToWindow,
|
|
zoomIndex,
|
|
setZoomIndex,
|
|
}: {
|
|
direction: Direction;
|
|
setDirection: (d: Direction) => void;
|
|
fitToWindow: () => void;
|
|
zoomIndex: number;
|
|
setZoomIndex: (updater: (i: number) => number) => void;
|
|
}) {
|
|
const group =
|
|
"flex items-center gap-0.5 px-0.5 [&:not(:first-child)]:border-l [&:not(:first-child)]:border-line-strong [&:not(:first-child)]:pl-1 [&:not(:first-child)]:ml-1";
|
|
const btn =
|
|
"flex size-7 items-center justify-center rounded text-fg-muted transition-colors hover:bg-overlay hover:text-fg-3 focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-teal-500";
|
|
const btnActive = "bg-overlay-strong text-fg-3";
|
|
const btnDisabled =
|
|
"disabled:opacity-30 disabled:hover:bg-transparent disabled:hover:text-fg-muted";
|
|
|
|
return (
|
|
<div
|
|
role="toolbar"
|
|
aria-label="Graph controls"
|
|
className="absolute right-3 top-3 z-10 flex items-center rounded-md border border-line bg-panel p-0.5"
|
|
>
|
|
<div className={group}>
|
|
<button
|
|
type="button"
|
|
title="Left to right"
|
|
onClick={() => setDirection("LR")}
|
|
aria-pressed={direction === "LR"}
|
|
className={`${btn} ${direction === "LR" ? btnActive : ""}`}
|
|
>
|
|
<ArrowRightIcon className="size-3.5" aria-hidden="true" />
|
|
</button>
|
|
<button
|
|
type="button"
|
|
title="Top to bottom"
|
|
onClick={() => setDirection("TB")}
|
|
aria-pressed={direction === "TB"}
|
|
className={`${btn} ${direction === "TB" ? btnActive : ""}`}
|
|
>
|
|
<ArrowDownIcon className="size-3.5" aria-hidden="true" />
|
|
</button>
|
|
</div>
|
|
<div className={group}>
|
|
<button type="button" title="Fit to window" onClick={fitToWindow} className={btn}>
|
|
<svg viewBox="0 0 14 14" fill="none" stroke="currentColor" className="size-3.5" aria-hidden="true">
|
|
<rect x="1" y="1" width="12" height="12" rx="1.5" strokeWidth="1.5" strokeDasharray="3 2" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<div className={group}>
|
|
<button
|
|
type="button"
|
|
title="Zoom out"
|
|
onClick={() => setZoomIndex((i) => Math.max(0, i - 1))}
|
|
disabled={zoomIndex === 0}
|
|
className={`${btn} ${btnDisabled}`}
|
|
>
|
|
<MinusIcon className="size-4" aria-hidden="true" />
|
|
</button>
|
|
<button
|
|
type="button"
|
|
title="Zoom in"
|
|
onClick={() => setZoomIndex((i) => Math.min(GRAPH_ZOOM_STEPS.length - 1, i + 1))}
|
|
disabled={zoomIndex === GRAPH_ZOOM_STEPS.length - 1}
|
|
className={`${btn} ${btnDisabled}`}
|
|
>
|
|
<PlusIcon className="size-4" aria-hidden="true" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|