Skip to content

Is --color-on-* defined against the fill or the muted fill? The bundled themes disagree #5282

Description

@cixzhang

Building the contrast-pair check in #5281 turned up a question the check cannot answer, because we have not decided it: is --color-on-error defined against --color-error, or against --color-error-muted?

The defaults say the former. --color-on-error is #FFFFFF and --color-error is #E3193B; white on that fill is 4.70:1, which is only a meaningful number if the label sits on the fill. #5019 is about the dark half of that same pair.

stone reads it the other way, deliberately and with comments:

// Text on top of matching status surface (badge fill, banner content).
'--color-on-error': ['#58413e', '#f9dcd7'],   // Red T30 / T90
// Status / Sentiment — T50 from palette for icons/borders (visible color)
'--color-error':    ['#58413e', '#dcc0bc'],   // Red T30 / T80
'--color-error-muted': ['#f9dcd7', '#dcc0bc'], // Red T90 / T80

In light mode --color-on-error and --color-error are the same colour, #58413e — 1:1. Nothing is broken on screen, because stone puts the label on --color-error-muted (#f9dcd7, a fine ratio) and uses --color-error for icons and borders. But under the defaults' reading, stone ships an invisible error label.

I measured every bundled theme against the defaults' reading. All seven fail something:

theme findings example
neutral 3 control boundary 1.48:1 light
stone 8 on-error == error in light (1:1)
y2k 1 control boundary 1.71:1 dark
butter 1 control boundary 1.75:1 light
chocolate 5 white on #FD0000 error fill, 4.06:1
gothic 2 control boundary 2.28:1 both modes
matcha 7 success label 3.58:1 light

Some of these are certainly real — chocolate's pure-red error fill with a white label is a near-miss under any reading, and --color-border-emphasized under 3:1 is a 1.4.11 problem regardless of what the neighbouring token means. Others are stone-style role disagreements.

I did not touch any of them, and I narrowed #5281 to pairs where a theme hand-wrote exactly one side, so it is silent on all seven. That keeps the tool honest but leaves the real question open:

  1. Decide the contract. Which token is the fill a --color-on-* label sits on? Write it into astryx docs color either way — right now a theme author has to guess, and stone and the defaults guessed differently.
  2. Then the both-sides-authored case becomes checkable, and fix(cli): warn when a theme overrides one side of a colour pair #5281 can widen to it.
  3. Independently of (1): the --color-border-emphasized findings do not depend on the contract. Those look like straightforward bugs in four themes.

Happy to take any of these once (1) is settled — it is a design call, not a tooling one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions