Skip to content

fix(ui): make the shared active toggle state clearly visible - #937

Merged
pascalandr merged 2 commits into
devfrom
fix/icon-toggle-active
Oct 13, 2026
Merged

pascalandr merged 2 commits into
devfrom
fix/icon-toggle-active

Conversation

@pascalandr

Copy link
Copy Markdown
Contributor

Summary

The shared active state of toggle buttons (.icon-toggle with aria-pressed, aria-expanded or data-active) was nearly invisible on light palettes. On the default light palette the active fill was ΔE 0.4 from the header surface, so search, command palette, web preview, utility windows and panel toggles gave almost no feedback.

The single shared rule now fills active toggles with a uniform accent tint: 40%, and 50% for active + hover. The ink is accent leaning 20% toward the existing per-palette --text-on-accent.

  • The icon keeps the text colour at ≥ 3:1 on every ready-made palette (lowest 3.34:1, Mist on hover).
  • No per-palette values and no new tokens.
  • Disabled toggles are excluded with zero-specificity :where().
  • Corners stay square; the focus ring is unchanged.

Because the rule is shared, the tint also applies to every other active .icon-toggle: Files eye toggles, diff toggles, Missions toggles and the interruption dock's expand toggle.

Validation

  • New icon-toggle-active.test.ts renders the real header on every ready-made palette and asserts:

    • ΔE ≥ 8 from the surface;
    • ΔE ≥ 6 from idle hover;
    • ΔE ≥ 2 between active and active + hover;
    • icon contrast ≥ 3:1.

    It fails on the previous rule.

  • palette-quality.test.ts 40/40.

  • UI typecheck clean.

  • 11 browser suites: 124 pass, 1 Electron-only skip.

An independent gatekeeper review will be published before the admin merge.

The shared active state of header and window toggles (`.icon-toggle` with
aria-pressed, aria-expanded or data-active) was nearly invisible on light
palettes: on the default light palette the active fill was ΔE 0.4 from the
header surface, so search, command palette, web preview, utility windows and
panel toggles gave almost no feedback when on.

The single shared rule now fills active toggles with a uniform accent tint:
color-mix(in oklab, accent-primary 80% / text-on-accent 20%) at 40%, and 50%
for active + hover, over whatever surface the button sits on. Leaning the
ink slightly toward the existing per-palette `--text-on-accent` keeps the
text-coloured icon at ≥ 3:1 on every ready-made palette (lowest 3.34:1, Mist
on hover) without per-palette values or new tokens. Disabled toggles are
excluded with zero-specificity :where(), so existing overrides still win;
corners stay square and the focus ring is unchanged.

A new browser test renders the real header on every ready-made palette and
asserts ΔE ≥ 8 from the surface, ≥ 6 from idle hover, ≥ 2 between active
and active + hover, and icon contrast ≥ 3:1; it fails on the previous rule.
Palette-quality (40/40), the UI typecheck and 11 browser suites (124 pass,
1 Electron-only skip) pass.

@pascalandr pascalandr left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent gatekeeper pass 1 on 7b91fc1: 2 P2 + 1 P3, merge held. Selectors and specificity are clean.

  • P2-1 Mission past-run rows (mission-recurrence-list.tsx:248, mission-recurrence-reader.tsx:32) are full-width text list selections using .icon-toggle. Their text drops below 4.5:1 on the 40% tint over the canvas (Mist 4.19, Dawn 4.03, Linen 4.22, Sage-light 4.23; more palettes at 50%). Fix: use the shared --list-item-highlight-* selection tokens there, as AGENTS.md specifies for Mission selection.
  • P2-2 SpeechActionButton (aria-pressed while playing) sits on message cards (surfaceMuted). Icon contrast while playing + hover is 2.94 on Mist and 2.99 on Dawn, so "≥ 3:1 on every palette" is false off the header surface. Fix: sample the message-card surface in the test and retune until both surfaces pass.
  • P3 AGENTS.md wording: the tool-output rail override is a legitimate existing exception, and the contrast claim should name the surfaces actually covered.

Verified: specificity (.tool-call-output-rail override still wins), no double tint, --text-on-accent available for built-in and custom palettes, oklab color-mix support, forced-colors unchanged, disabled exclusion, deterministic test. Typecheck; palette-quality 40/40; icon-toggle-active 1/1; header-windows 41/41; git-history 18/18; interruption-dock 19/19; mission-panel-layout 6/6; view-menu 2/2. Fixes and another pass follow.

Address the first independent review of the accent-tinted active state.

Mission past-run rows are full-width text list selections, not icon
toggles: they drop `.icon-toggle` (keeping aria-pressed) and use the shared
`--list-item-highlight-*` selection treatment, keeping selected text at
>= 4.5:1 (4.82:1 lowest) on all ready-made palettes.

The playing speech button on message cards fell below 3:1 on the 50%
active + hover fill (Mist, Dawn). No accent/--text-on-accent lean fixes
every palette on its own, so the single rule keeps the 80/20 lean and mixes
10% toward --surface-base, which always sits opposite the primary-text
icon. The ink is a custom property declared on the active rule itself, so
it resolves per element without new tokens or per-palette values; the
uniform 40% / 50% intent is unchanged.

The browser test now samples real active toggles on the session header,
sidebar header, right-panel tabs, user and assistant message cards (the real
speech button), the interruption dock header and the transcript canvas,
plus a selected past-run row, across all 17 ready-made palettes (lowest
icon contrast 3.20:1). AGENTS.md names those surfaces and the legitimate
tool-output rail override. Palette-quality, icon-toggle-active, header,
git-history, interruption-dock, mission and view-menu suites pass; UI
typecheck clean.

@pascalandr pascalandr left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent gatekeeper pass 2 on bdfe1d1: ZERO FINDINGS.

All three pass-1 findings are fixed:

  • Past-run rows: they now use list-highlight selection; selected text is ≥ 4.82:1.
  • Icon contrast: independently measured ≥ 3.20:1 across 17 palettes × 7 real surfaces; the Mist assistant card went from 2.94 to 3.26.
  • AGENTS.md: the wording is accurate.

The per-rule --icon-toggle-active-ink approach keeps specificity, transitions and the output-rail override intact; no text rows still use .icon-toggle; the fixture change is isolated to ?assistant.

Validation: typecheck clean; palette-quality 40/40; icon-toggle-active 1/1; header-windows 41/41; git-history 18/18; interruption-dock 19/19; mission-panel-layout 6/6; mission-recurrence 16/16; view-menu 2/2; mission-passage-history 6/6.

Proceeding with the requested admin merge.

@pascalandr
pascalandr merged commit a4c12da into dev Oct 13, 2026
11 of 13 checks passed
@pascalandr
pascalandr deleted the fix/icon-toggle-active branch October 13, 2026 09:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant