Compare commits

...
Author SHA1 Message Date
iris
e8d391be13 fix(#1001): replace var(--mauve) with var(--purple) throughout dashboard.css
--mauve is not declared in base.css; the palette exposes the Catppuccin
Mocha mauve colour as --purple (#cba6f7). Affected rules:
  .btn-move colour + border
  .logs-back colour (back-link on logs page)
  .logs-tab.logs-tab-active text colour (issue #1001 — tab shows no state)
  border colour on a schedule input

Combined with the --surface1/2 fix from the previous commit, the active
log tab now shows a solid background (--border) with purple text (--purple).
2026-06-01 19:52:21 +02:00
iris
e045a29508 fix(#994,#996): replace undefined CSS vars; guard overflow rebuild when open
dashboard.css used var(--surface0/1/2) and var(--text) throughout the
agent context menu, tabbar overflow dropdown, and logs toolbar — none
of which are declared in base.css (the palette only defines --bg-elev,
--border, --purple-dim, --fg etc). This caused all three dropdowns to
render with a transparent background (issue #996).

Replacements:
  --surface0  → --bg-elev   (dropdown background)
  --surface1  → --border    (hover / active state)
  --surface2  → --purple-dim (border / separator)
  --text      → --fg        (label colour)

Also addresses two argus yellows from the PR #997 review:
- Skip updateTabbarOverflow() early when the dropdown is open; avoids
  DOM flicker from the 1s badge-update tick while the menu is visible.
- Fall back to 32px when overflowBtn.offsetWidth === 0 (hidden on the
  first render) so the initial width measurement is not off.
2026-06-01 19:49:43 +02:00
2 changed files with 27 additions and 21 deletions

View file

@ -144,8 +144,8 @@ body.dashboard-shell {
right: 0; right: 0;
top: calc(100% + 2px); top: calc(100% + 2px);
z-index: 100; z-index: 100;
background: var(--surface0); background: var(--bg-elev);
border: 1px solid var(--surface2); border: 1px solid var(--purple-dim);
border-radius: 6px; border-radius: 6px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
list-style: none; list-style: none;
@ -163,7 +163,7 @@ body.dashboard-shell {
width: 100%; width: 100%;
background: none; background: none;
border: none; border: none;
color: var(--text); color: var(--fg);
font-family: inherit; font-family: inherit;
font-size: 0.88em; font-size: 0.88em;
letter-spacing: 0.05em; letter-spacing: 0.05em;
@ -173,7 +173,7 @@ body.dashboard-shell {
cursor: pointer; cursor: pointer;
} }
.tabbar-overflow-item:hover { .tabbar-overflow-item:hover {
background: var(--surface1); background: var(--border);
color: var(--purple); color: var(--purple);
} }
.tabbar-overflow-item-active { .tabbar-overflow-item-active {
@ -447,8 +447,8 @@ a:hover {
} }
.agent-menu-btn:hover, .agent-menu-btn:hover,
.agent-menu-btn:focus-visible { .agent-menu-btn:focus-visible {
background: var(--surface1); background: var(--border);
color: var(--text); color: var(--fg);
opacity: 1; opacity: 1;
} }
.agent-menu-btn:focus-visible { .agent-menu-btn:focus-visible {
@ -460,8 +460,8 @@ a:hover {
right: 0; right: 0;
top: calc(100% + 2px); top: calc(100% + 2px);
z-index: 200; z-index: 200;
background: var(--surface0); background: var(--bg-elev);
border: 1px solid var(--surface2); border: 1px solid var(--purple-dim);
border-radius: 6px; border-radius: 6px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45); box-shadow: 0 4px 16px rgba(0, 0, 0, 0.45);
list-style: none; list-style: none;
@ -475,7 +475,7 @@ a:hover {
width: 100%; width: 100%;
background: none; background: none;
border: none; border: none;
color: var(--text); color: var(--fg);
font-family: inherit; font-family: inherit;
font-size: 0.82em; font-size: 0.82em;
letter-spacing: 0.01em; letter-spacing: 0.01em;
@ -484,11 +484,11 @@ a:hover {
cursor: pointer; cursor: pointer;
} }
.agent-menu-item:hover { .agent-menu-item:hover {
background: var(--surface1); background: var(--border);
} }
.agent-menu-sep { .agent-menu-sep {
height: 1px; height: 1px;
background: var(--surface2); background: var(--purple-dim);
margin: 0.3em 0; margin: 0.3em 0;
} }
/* Pending state splits queued vs running queued ops show only /* Pending state splits queued vs running queued ops show only
@ -1206,7 +1206,7 @@ ul form.inline { display: inline-block; }
/* M0V3 affordance (selection bar) mauve reads as "structural /* M0V3 affordance (selection bar) mauve reads as "structural
change" rather than the destructive red / amber chrome of change" rather than the destructive red / amber chrome of
destroy / rebuild. See docs/web-ui.md::Selection bar. */ destroy / rebuild. See docs/web-ui.md::Selection bar. */
.btn-move { color: var(--mauve); border-color: var(--mauve); font-size: 0.75em; padding: 0.15em 0.5em; margin-left: 0.6em; } .btn-move { color: var(--purple); border-color: var(--purple); font-size: 0.75em; padding: 0.15em 0.5em; margin-left: 0.6em; }
.btn-talk { color: var(--cyan); border-color: var(--cyan); } .btn-talk { color: var(--cyan); border-color: var(--cyan); }
.btn-spawn { color: var(--amber); border-color: var(--amber); } .btn-spawn { color: var(--amber); border-color: var(--amber); }
.btn-fire-now { color: var(--mauve, #cba6f7); border-color: var(--mauve, #cba6f7); } .btn-fire-now { color: var(--mauve, #cba6f7); border-color: var(--mauve, #cba6f7); }
@ -1984,7 +1984,7 @@ body.logs-shell {
} }
.logs-back { .logs-back {
color: var(--mauve); color: var(--purple);
text-decoration: none; text-decoration: none;
font-size: 0.88em; font-size: 0.88em;
white-space: nowrap; white-space: nowrap;
@ -2016,10 +2016,10 @@ body.logs-shell {
letter-spacing: 0.05em; letter-spacing: 0.05em;
transition: background 100ms, color 100ms; transition: background 100ms, color 100ms;
} }
.logs-tab:hover { background: var(--surface1); color: var(--text); } .logs-tab:hover { background: var(--border); color: var(--fg); }
.logs-tab.logs-tab-active { .logs-tab.logs-tab-active {
background: var(--surface1); background: var(--border);
color: var(--mauve); color: var(--purple);
} }
.logs-main { .logs-main {
@ -2037,9 +2037,9 @@ body.logs-shell {
} }
.logs-toolbar .journal-unit { .logs-toolbar .journal-unit {
background: var(--surface1); background: var(--border);
color: var(--text); color: var(--fg);
border: 1px solid var(--surface2); border: 1px solid var(--purple-dim);
border-radius: 4px; border-radius: 4px;
padding: 0.25em 0.5em; padding: 0.25em 0.5em;
font-size: 0.85em; font-size: 0.85em;
@ -2459,7 +2459,7 @@ body.dashboard-shell.has-selection { padding-bottom: 4.5em; }
font-size: 0.75em; font-size: 0.75em;
background: var(--bg); background: var(--bg);
color: var(--fg); color: var(--fg);
border: 1px solid var(--mauve); border: 1px solid var(--purple);
border-radius: 2px; border-radius: 2px;
padding: 0.1em 0.3em; padding: 0.1em 0.3em;
max-width: 16em; max-width: 16em;

View file

@ -3438,6 +3438,9 @@ window.marked = marked;
function updateTabbarOverflow() { function updateTabbarOverflow() {
const tabbar = $('tabbar'); const tabbar = $('tabbar');
if (!tabbar || !overflowBtn || !overflowDrop) return; if (!tabbar || !overflowBtn || !overflowDrop) return;
// Skip dropdown rebuild while it is open — the 1s badge tick would
// replace DOM nodes and cause a flicker mid-interaction.
if (overflowOpen) return;
// Collect all tabs that are not JS-hidden (P33RS/M4TR1X may be hidden // Collect all tabs that are not JS-hidden (P33RS/M4TR1X may be hidden
// by feature-gating) and not already removed from the DOM. // by feature-gating) and not already removed from the DOM.
@ -3452,7 +3455,10 @@ window.marked = marked;
// Step 2: measure available width (bar width minus overflow-btn width). // Step 2: measure available width (bar width minus overflow-btn width).
// We must read layout AFTER restoring all dynamic tabs. // We must read layout AFTER restoring all dynamic tabs.
const availWidth = tabbar.clientWidth - overflowBtn.offsetWidth - 8; // overflowBtn may be hidden (offsetWidth=0) on the very first call; fall
// back to a 32px estimate so the first-pass measurement isn't off.
const btnW = overflowBtn.offsetWidth || 32;
const availWidth = tabbar.clientWidth - btnW - 8;
// Step 3: walk dynamic tabs left-to-right, accumulating widths. // Step 3: walk dynamic tabs left-to-right, accumulating widths.
// Any that go over the available width get overflowed. // Any that go over the available width get overflowed.