feat(app): status rings on panels + sidebar aggregate badge from state events

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-09 23:11:46 +07:00
parent c35585755e
commit d36548ff39
7 changed files with 79 additions and 9 deletions
+16 -2
View File
@@ -1,4 +1,18 @@
import type { Group, WorkspaceView } from "./layoutTypes";
import type { Group, WorkspaceView, SurfaceState } from "./layoutTypes";
const RING: Record<SurfaceState | "stopped", string> = {
error: "#F4544E", wait: "#F2B84B", work: "#4C8DFF", done: "#3FB950", idle: "#5A6573", stopped: "#5A6573",
};
function aggregate(w: WorkspaceView): SurfaceState | "stopped" {
const order: SurfaceState[] = ["error", "wait", "work", "done", "idle"];
const running = Object.values(w.surfaces).filter((s) => s.running);
if (running.length === 0) return "stopped";
for (const st of order) {
if (running.some((s) => s.state === st)) return st;
}
return "idle";
}
export function Sidebar({
groups, workspaces, activeId, onSelect, onNew,
@@ -19,7 +33,7 @@ export function Sidebar({
background: w.id === activeId ? "#1A2029" : "transparent", fontFamily: "Inter", fontSize: 13,
color: w.id === activeId ? "#E6EDF3" : "#8B97A6",
}}>
<span style={{ width: 10, height: 10, borderRadius: "50%", border: "2px solid #5A6573" }} />
<span style={{ width: 10, height: 10, borderRadius: "50%", border: `2px solid ${RING[aggregate(w)]}`, boxSizing: "border-box" }} />
<span style={{ flex: 1 }}>{w.name}</span>
{w.unread && <span style={{ width: 7, height: 7, borderRadius: "50%", background: "#4C8DFF" }} />}
<span style={{ fontFamily: "monospace", fontSize: 11, color: "#5A6573" }}>{Object.keys(w.surfaces).length}</span>