facebook / facebook/astryx

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

Open
#5,282 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
13.1k
Forks
1.1k
Avg merge
1d 15h
Merged PRs (30d)
687

Description

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:

```ts
// 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 #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.

Contributor guide

Open the contributing guide

Research direction

Start at the `astryx docs color` entry point and review the defaults, stone theme comments, and findings listed here. Decide and document whether `--color-on-*` is measured against the fill or muted fill; done means the contract is explicit and #5281 can be revisited without guessing.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
design, documentation
Issue type
Documentation
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.