diff --git a/app/src/components/ThemeSamplePage.js b/app/src/components/ThemeSamplePage.js index 1b0e10f3..40e55625 100644 --- a/app/src/components/ThemeSamplePage.js +++ b/app/src/components/ThemeSamplePage.js @@ -355,8 +355,9 @@ export function ThemeSamplePage() { Light and dark spend a colour on each. Night and amber have only one hue, so a role is a step on a brightness ramp instead; that is why an error and an info toast used to be the same pixel there. Severity climbs in the order - shown for those two themes, and danger is never quieter than - ordinary text. + shown for those two themes, and both warning and{' '} + danger are brighter than ordinary text — with no hue to carry + "look at this", brighter is the only thing left.

diff --git a/app/src/components/ui/ui-layout.cy.js b/app/src/components/ui/ui-layout.cy.js index 340ac4e9..35175ca6 100644 --- a/app/src/components/ui/ui-layout.cy.js +++ b/app/src/components/ui/ui-layout.cy.js @@ -298,19 +298,26 @@ describe('semantic roles read as severity in every theme', () => { }); }); - it(`makes danger at least as loud as ordinary text in ${theme}`, () => { + it(`makes warning and danger louder than ordinary text in ${theme}`, () => { /* - * Also only here. A light theme's text is near-black at ~14:1 and no danger - * colour will ever match it; on a single hue the roles and the text are drawn - * from the same ramp, so the loudest role must not be quieter than the prose. + * Only here. A light theme's text is near-black at ~14:1 and no warning colour + * will ever match it -- there, hue is what marks a reading as flagged. On a + * single hue the roles and the text come off the same ramp, so anything meaning + * "look at this" has to outrank the prose or it does not read as flagged at all. + * + * This is the assertion the Status page needed: an uncoloured load reading + * inherits `--text`, and warning used to sit just below it. */ cy.mountUI(roles, {theme}); cy.get('.wrolpi-panel').should(() => { const {panel, text, roles} = roleColours(); - const danger = roles.find(r => r.role === 'danger').colour; - expect(contrast(danger, panel), 'danger vs --text against the panel') - .to.be.at.least(contrast(text, panel) * 0.95); + const prose = contrast(text, panel); + ['warning', 'danger'].forEach((name) => { + const role = roles.find(r => r.role === name).colour; + expect(contrast(role, panel), `${name} against --text on the panel`) + .to.be.greaterThan(prose); + }); }); }); }); @@ -366,23 +373,15 @@ describe('a load reading ranks itself in the monochrome themes', () => { Cypress.$('.wrolpi-panel')[0]).backgroundColor); expect(new Set([fine, warning, danger]).size, 'three distinct readings').to.equal(3); + /* + * Both flagged readings outrank a plain one. This is what the ramp change + * bought: warning used to sit just UNDER `--text`, so a machine under load + * rendered marginally quieter than a healthy one. + */ + expect(contrast(warning, panel), 'warning is louder than a plain reading') + .to.be.greaterThan(contrast(fine, panel)); expect(contrast(danger, panel), 'danger is louder than warning') .to.be.greaterThan(contrast(warning, panel)); - expect(contrast(danger, panel), 'danger is louder than a plain reading') - .to.be.greaterThan(contrast(fine, panel)); - - /* - * NOT asserted: that warning outranks a plain reading. It does not, and that - * is a live question rather than an oversight -- an uncoloured value inherits - * `--text`, which in night is 4.98:1 against 4.91:1 for `--warning`. So a - * machine under load is marginally QUIETER than one that is fine. - * - * Lifting warning above text is a palette change, not a call-site one: on a - * dark panel the only way up is lightness, and night's danger would desaturate - * from #ff3e3e to about #ff5d5d -- trading the theme's "red only" character - * for loudness. Worth a deliberate decision, so it is flagged rather than - * quietly made here. - */ }); }); }); diff --git a/app/src/themes/tokens.css b/app/src/themes/tokens.css index ac2597cb..bd346f95 100644 --- a/app/src/themes/tokens.css +++ b/app/src/themes/tokens.css @@ -80,8 +80,18 @@ html[data-theme="light"] { * In the MONOCHROME themes only (night and amber): * - the order neutral < info < success < warning < danger is strictly increasing in * contrast against the panel, so severity reads as brightness with no hue to help; - * - danger reaches that theme's own `--text` brightness, so the loudest role is never - * quieter than ordinary prose. + * - BOTH warning and danger reach that theme's own `--text` brightness. Anything that + * means "look at this" has to be louder than the prose around it, and with no hue to + * carry the signal, louder means brighter. Warning used to sit just under `--text` + * (4.91 against 4.98 in night), so a machine under load rendered marginally quieter + * than a healthy one. + * + * Getting warning and danger above `--text` costs a little saturation, and it is worth + * knowing exactly how little: red contributes only 21% of luminance, so in night nothing + * above ~4.9:1 can be a pure hue -- `#ff0000` itself is only 4.99:1 there. `--text` is + * already `#e04a4a`, carrying 74 of green and blue. The new `--warning` `#f54040` carries + * 64, LESS than the text beside it; only `--danger` `#ff5757` goes further, at 87. The + * theme's red-only character survives; a pure-hue ramp was never available. * * Those last two are NOT true of light and dark and must not be made true. There a role * is a hue, and the contrast order is an accident of which hues were chosen -- blue is @@ -174,8 +184,8 @@ html[data-theme="night"] { --neutral: #992c2c; --info: #c02929; --success: #e02323; - --warning: #ee3434; - --danger: #ff3e3e; + --warning: #f54040; + --danger: #ff5757; } /* Amber: a monochrome amber terminal palette, same flat style as the rest. */ @@ -215,8 +225,8 @@ html[data-theme="amber"] { --neutral: #815825; --info: #b06e1f; --success: #d37c11; - --warning: #f18806; - --danger: #ff9e29; + --warning: #fa9f31; + --danger: #ffb760; } /* ------------------------------------------------------------------------- */