refactor(maestro): drop per-session colour and pane glow
The sidebar row dot, the pane top strip and the mobile pill dot all painted a hashed per-session colour; the focused pane added an outer accent glow on top of its ring. Removes the colour concept entirely along with the glow, leaving the flat accent ring as the only focus mark.
This commit is contained in:
+3
-9
@@ -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<string>;
|
||||
focused: string | null;
|
||||
colors: Map<string, string>;
|
||||
}
|
||||
|
||||
/** 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<HTMLElement>(".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();
|
||||
},
|
||||
|
||||
+3
-15
@@ -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<string, string> {
|
||||
const m = new Map<string, string>();
|
||||
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 {
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
+4
-41
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user