diff --git a/web/src/catalog.ts b/web/src/catalog.ts index 2f1a4f2..0d58035 100644 --- a/web/src/catalog.ts +++ b/web/src/catalog.ts @@ -327,12 +327,10 @@ export function renderTopbar(store: CatalogStore, onToggleSidebar?: () => void): } /** Two-tier sidebar highlight state (issue #33): which sessions are open in some - * pane (quiet), which one is focused (loud), and a stable per-session colour so - * a row maps to its pane. */ + * pane (quiet), and which one is focused (loud). */ export interface SidebarHighlights { open: Set; focused: string | null; - colors: Map; } /** Live handle to the persistent sidebar (built once, survives navigation). */ @@ -342,7 +340,7 @@ export interface SidebarHandle { /** Highlight the row for `id` (or clear it with `null`) as the focused session. * Back-compat shim over {@link setHighlights}. */ setActive(id: string | null): void; - /** Apply the full open/focused/colour highlight state. */ + /** Apply the full open/focused highlight state. */ setHighlights(h: SidebarHighlights): void; /** Tear down the store subscription + listeners. */ dispose(): void; @@ -451,7 +449,7 @@ export function renderSidebar(store: CatalogStore, opts: SidebarOptions = {}): S refresh(); }); - let highlights: SidebarHighlights = { open: new Set(), focused: null, colors: new Map() }; + let highlights: SidebarHighlights = { open: new Set(), focused: null }; const applyHighlights = () => { for (const n of treeHost.querySelectorAll(".tree-leaf")) { const id = n.dataset.sessionId; @@ -460,9 +458,6 @@ export function renderSidebar(store: CatalogStore, opts: SidebarOptions = {}): S const open = highlights.open.has(id); n.classList.toggle("is-active", focused); n.classList.toggle("is-open", open && !focused); - const color = highlights.colors.get(id); - if (color && (open || focused)) n.style.setProperty("--mv-color", color); - else n.style.removeProperty("--mv-color"); } }; @@ -515,7 +510,6 @@ export function renderSidebar(store: CatalogStore, opts: SidebarOptions = {}): S highlights = { open: id ? new Set([id]) : new Set(), focused: id, - colors: new Map(), }; applyHighlights(); }, diff --git a/web/src/multiview.ts b/web/src/multiview.ts index f19de89..3da26a8 100644 --- a/web/src/multiview.ts +++ b/web/src/multiview.ts @@ -22,7 +22,6 @@ import { removeLeaf, splitLeaf, } from "./layout.js"; -import { sessionColor } from "./sessioncolor.js"; import type { AttachInfo } from "./attach.js"; import { createSpawnForm, type SpawnFormHandle } from "./spawnForm.js"; @@ -97,12 +96,6 @@ export function createMultiView(opts: MultiViewOptions): MultiView { // ---- highlight helpers ---- - function colorMap(): Map { - const m = new Map(); - for (const id of openSessions(layout)) m.set(id, sessionColor(id)); - return m; - } - function focusedLeafSession(): string | null { const tab = activeTab(layout); const fl = tab.focusedLeafId ? findLeaf(tab.root, tab.focusedLeafId) : null; @@ -120,7 +113,6 @@ export function createMultiView(opts: MultiViewOptions): MultiView { sidebar.setHighlights({ open: openSessions(layout), focused: focusedLeafSession(), - colors: colorMap(), }); } @@ -142,10 +134,7 @@ export function createMultiView(opts: MultiViewOptions): MultiView { const pane = document.createElement("div"); pane.className = "mv-pane"; pane.dataset.leafId = leaf.id; - if (leaf.sessionId) { - pane.dataset.sessionId = leaf.sessionId; - pane.style.setProperty("--mv-color", sessionColor(leaf.sessionId)); - } + if (leaf.sessionId) pane.dataset.sessionId = leaf.sessionId; const host = document.createElement("div"); host.className = "mv-pane-host"; @@ -482,7 +471,7 @@ export function createMultiView(opts: MultiViewOptions): MultiView { pool.setVisible([]); pool.setFocus(null); canvas.appendChild(renderWelcome()); - sidebar.setHighlights({ open: openSessions(layout), focused: null, colors: colorMap() }); + sidebar.setHighlights({ open: openSessions(layout), focused: null }); persist(); return; } @@ -523,7 +512,6 @@ export function createMultiView(opts: MultiViewOptions): MultiView { pill.type = "button"; pill.className = "mv-pill" + (l.id === focused.id ? " is-active" : ""); pill.textContent = l.sessionId ? (infoFor(l.sessionId)?.name ?? l.sessionId.slice(0, 8)) : "empty"; - if (l.sessionId) pill.style.setProperty("--mv-color", sessionColor(l.sessionId)); pill.addEventListener("click", () => { tab.focusedLeafId = l.id; render(); @@ -543,7 +531,7 @@ export function createMultiView(opts: MultiViewOptions): MultiView { focused.sessionId ? [{ id: focused.sessionId, pane: pane.host, info: infoFor(focused.sessionId) }] : [], ); pool.setFocus(focused.sessionId ?? null); - sidebar.setHighlights({ open: openSessions(layout), focused: focused.sessionId ?? null, colors: colorMap() }); + sidebar.setHighlights({ open: openSessions(layout), focused: focused.sessionId ?? null }); } function closeSession(sessionId: string): void { diff --git a/web/src/sessioncolor.ts b/web/src/sessioncolor.ts deleted file mode 100644 index a61caab..0000000 --- a/web/src/sessioncolor.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Stable per-session accent colour, used to map a sidebar row to the pane -// showing that session (issue #33). Hash the session id into a fixed OKLCH -// palette tuned to the maestro tokens; collisions are tolerated when there are -// more open sessions than hues — the colour is a hint, not an identity. - -import type { Uuid } from "./types.js"; - -const PALETTE = [ - "oklch(0.80 0.13 152)", // green (the house accent) - "oklch(0.80 0.12 90)", // amber - "oklch(0.76 0.13 30)", // coral - "oklch(0.78 0.11 210)", // teal - "oklch(0.74 0.13 265)", // blue - "oklch(0.76 0.14 320)", // magenta - "oklch(0.80 0.11 60)", // gold - "oklch(0.78 0.12 185)", // cyan -]; - -export function sessionColor(id: Uuid): string { - let h = 0; - for (let i = 0; i < id.length; i++) h = (h * 31 + id.charCodeAt(i)) >>> 0; - return PALETTE[h % PALETTE.length]; -} diff --git a/web/src/styles.css b/web/src/styles.css index ddb2e04..0f729a4 100644 --- a/web/src/styles.css +++ b/web/src/styles.css @@ -2301,20 +2301,10 @@ input.leaf-rename:focus { min-width: 0; min-height: 0; } -/* per-session colour strip — maps a pane to its sidebar row */ -.mv-pane::before { - content: ""; - position: absolute; - inset: 0 0 auto 0; - height: 2px; - background: var(--mv-color, transparent); - z-index: 3; - pointer-events: none; -} -/* focused pane: accent ring + glow, full strength */ +/* focused pane: accent ring, full strength */ .mv-pane.is-focused { border-color: var(--accent); - box-shadow: inset 0 0 0 1px var(--accent), 0 0 22px -8px var(--accent-ring); + box-shadow: inset 0 0 0 1px var(--accent); } /* unfocused panes recede so the eye finds the live one */ .mv-pane:not(.is-focused) { @@ -2417,31 +2407,12 @@ input.leaf-rename:focus { border-radius: var(--r-1); } -/* sidebar two-tier highlight + colour dot (issue #33). +/* sidebar two-tier highlight (issue #33). .is-active = focused pane (loud, from existing rule); .is-open = open - elsewhere (quiet). The dot uses the session's colour so a row maps to a pane. */ + elsewhere (quiet). */ .tree-leaf.is-open { background: color-mix(in oklab, var(--accent) 6%, transparent); } -.tree-leaf.is-open::after, -.tree-leaf.is-active::after { - content: ""; - position: absolute; - right: 9px; - top: 50%; - width: 7px; - height: 7px; - margin-top: -3.5px; - border-radius: 50%; - background: var(--mv-color, var(--accent)); - pointer-events: none; -} -.tree-leaf.is-open::after { - opacity: 0.7; -} -.tree-leaf.is-active::after { - box-shadow: 0 0 8px var(--mv-color, var(--accent-ring)); -} /* ========================================================================= multi-view mobile (#35): below 860px the split tree projects to a pill strip @@ -2486,14 +2457,6 @@ input.leaf-rename:focus { cursor: pointer; border: 1px solid transparent; } -.mv-pill::before { - content: ""; - width: 7px; - height: 7px; - border-radius: 50%; - background: var(--mv-color, var(--faint)); - flex: none; -} .mv-pill.is-active { background: var(--accent-tint); color: var(--accent-strong);