fix(theme): derive button text colour from accent luminance - #6108
fix(theme): derive button text colour from accent luminance#6108YahyaZekry wants to merge 5 commits into
Conversation
46 rules in static/style.css (plus 5 inline styles in admin.js, document.js, settings.js and compare/scoreboard.js) pair a `background: var(--red)` with a hardcoded `color: #fff`. Because --red is theme-configurable, several built-in themes render unreadable text on their own buttons -- terminal is 1.37:1, ume 1.97, paper 2.24, forest 2.35, ocean 2.42, cute 2.68, all below the 3:1 large-text floor. Adds an `--on-accent` token, recomputed in applyColors() from --red's WCAG relative luminance: dark text when white would fall under 3:1, white otherwise. Every hardcoded site now reads the token. Contrast against --red, before -> after: terminal 1.37 -> 13.13 ume 1.97 -> 9.11 paper 2.24 -> 8.00 forest 2.35 -> 7.64 ocean 2.42 -> 7.40 cute 2.68 -> 6.69 Themes already at or above 3:1 are untouched, so the visual change is limited to the six that were failing. HSL lightness would not work here: #e06c75 and #f2c14e have nearly identical HSL-L but 0.27 vs 0.56 relative luminance, because the WCAG formula weights green (0.7152) far above red (0.2126) and blue (0.0722). models.js's IMG badge is deliberately left alone -- its background is a fixed purple fallback, not --red.
Review feedback: --on-accent was derived from --red alone, but the send button's background is independently configurable via --send-btn-bg / --send-btn-hover, and those overrides are applied after the token is computed. A dark --red with a light custom send button therefore kept white text on a light surface -- e.g. --red #e06c75 with --send-btn-bg #f2c14e left #fff at 1.68:1. Each independently configurable accent surface now gets a foreground derived from the background it actually renders, resolved after the advanced overrides are applied: --on-accent <- --red (unchanged consumers) --on-send-btn <- resolved --send-btn-bg --on-send-btn-hover <- resolved --send-btn-hover --on-send-btn-newchat-hover <- that hover colour mixed 85% into --panel The new-chat state is a third surface because its background is itself a color-mix(); _mixSrgb() reproduces the CSS mix so it can be measured rather than approximated. Repointed .send-btn, .send-btn:hover, .send-btn.newchat-mode:hover and .ge-ai-command-run at the matching token; no rule now pairs --on-accent with a send-button background. Adds tests/test_theme_accent_foreground_js.py, which runs the derivation helpers under Node with a dark accent plus a light send-button override and asserts the two foregrounds differ, that reusing the accent's foreground would drop below 3:1, and that every surface clears 3:1 against its own background. A second test scans style.css so the mismatch cannot reappear.
|
Good catch — you're right, and the reproduction is exact. Pushed
The new-chat state needed its own token because its background is itself a On coverage: You're also right that the console snippet in the description only proved |
|
@YahyaZekry can you refresh screenshots? |
Summary
46 rules in
static/style.css, plus 5 inline styles inadmin.js,document.js,settings.jsandcompare/scoreboard.js, pair abackground: var(--red)with a hardcodedcolor: #fff. Because--redis theme-configurable, six built-in themes currently render text on their own buttons below the 3:1 large-text floor —terminalis 1.37:1,ume1.97,paper2.24,forest2.35,ocean2.42,cute2.68. This adds an--on-accenttoken, recomputed inapplyColors()from--red's WCAG relative luminance (dark text when white would fall under 3:1, white otherwise), and points every hardcoded site at it. The threshold is deliberately 3:1 so only the six failing themes change appearance; the other ten keep white exactly as today.Target branch
dev, notmain.Linked Issue
Fixes #6109
Type of Change
Checklist
devdocker compose up) and verified the change works end-to-end. See the note under Testing about which tree was run.How to Test
docker compose up -d --buildand open the app..admin-btn-add), and any primary/confirm button. Before this change the label is white on a light accent and effectively unreadable; after it, the label is near-black.Measured contrast against
--red, before → after: terminal 1.37 → 13.13, ume 1.97 → 9.11, paper 2.24 → 8.00, forest 2.35 → 7.64, ocean 2.42 → 7.40, cute 2.68 → 6.69. Worst case across all 16 themes goes from 1.37 to 3.03.Scope note on the "ran the app" checkbox: I run this fix in my own fork, which is where I verified it end-to-end in the browser (measured
.admin-btn-addat 10.68:1 live, up from ~1.68:1) and where it has been in daily use. I did not separately boot this exact branch offdev; the change is identical, but I'd rather state that precisely than overclaim.node --checkpasses on every changed JS file and the stylesheet's braces balance.Visual / UI changes — REQUIRED if you touched anything that renders
#fffliterals in favour of a token derived from the existing--red, and adds one variable alongside the existing--bg/--fg/--panel/--border/--redset. No new classes, no emoji, no font or theme-system changes.Screenshots / clips
Before — white label on a light accent, unreadable:
After —
--on-accentresolves to near-black:Same screen (Settings → Email), same build, only
--on-accentdiffers.Captured on a custom theme whose
--redis a light amber (#f2c14e), which puts it in the same failing band as the shippedcute/terminal/umethemes — it exercises the identical code path, just with an accent that makes the difference easy to see side by side. The--on-accentvalue is derived from--redalone, so behaviour is the same for any theme below the 3:1 threshold.Disclosure. I use an LLM agent as part of my workflow, so I have not checked the "not an LLM agent" box — checking it would be untrue. Per CONTRIBUTING I opened #6109 first; this PR is the proposed implementation attached to it, not a bulk drop. It is one focused fix, hand-reviewed, with the reasoning and measurements above. If you'd rather discuss it on the issue and have me close this, say the word and I will.