feat(ui,web): Phase 2 — Shared Components & Terminal Panel (#449) (#452)
All checks were successful
ci/woodpecker/push/orchestrator Pipeline was successful
ci/woodpecker/push/api Pipeline was successful
ci/woodpecker/push/web Pipeline was successful

Co-authored-by: Jason Woltje <jason@diversecanvas.com>
Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #452.
This commit is contained in:
2026-02-22 21:12:13 +00:00
committed by jason.woltje
parent a5ed260fbd
commit 716f230f72
20 changed files with 1297 additions and 116 deletions

View File

@@ -0,0 +1,99 @@
import { useState } from "react";
import type { ReactElement } from "react";
export interface MetricCell {
label: string;
value: string;
color: string; // CSS color, e.g., "var(--ms-blue-400)"
trend?: {
direction: "up" | "down" | "neutral";
text: string;
};
}
export interface MetricsStripProps {
cells: MetricCell[];
className?: string;
}
function MetricCellItem({ cell, isFirst }: { cell: MetricCell; isFirst: boolean }): ReactElement {
const [hovered, setHovered] = useState(false);
const trendColor =
cell.trend?.direction === "up"
? "var(--success)"
: cell.trend?.direction === "down"
? "var(--danger)"
: "var(--muted)";
return (
<div
onMouseEnter={(): void => {
setHovered(true);
}}
onMouseLeave={(): void => {
setHovered(false);
}}
style={{
padding: "14px 16px",
background: hovered ? "var(--surface-2)" : "var(--surface)",
borderLeft: isFirst ? "none" : "1px solid var(--border)",
borderTop: `2px solid ${cell.color}`,
transition: "background 0.15s ease",
}}
>
<div
style={{
fontSize: "1.4rem",
fontWeight: 800,
fontFamily: "var(--mono)",
lineHeight: 1.1,
color: cell.color,
}}
>
{cell.value}
</div>
<div
style={{
fontSize: "0.72rem",
color: "var(--muted)",
marginTop: 3,
whiteSpace: "nowrap",
}}
>
{cell.label}
</div>
{cell.trend && (
<div
style={{
fontSize: "0.68rem",
fontFamily: "var(--mono)",
marginTop: 4,
color: trendColor,
}}
>
{cell.trend.text}
</div>
)}
</div>
);
}
export function MetricsStrip({ cells, className = "" }: MetricsStripProps): ReactElement {
return (
<div
className={className}
style={{
display: "grid",
gridTemplateColumns: `repeat(${String(cells.length)}, 1fr)`,
borderRadius: "var(--r-lg)",
overflow: "hidden",
border: "1px solid var(--border)",
}}
>
{cells.map((cell, index) => (
<MetricCellItem key={cell.label} cell={cell} isFirst={index === 0} />
))}
</div>
);
}