Clean up the 23 raw colours `@astryx/no-raw-color` reports, then promote it to `error`
- Dominant language
- TypeScript
- Stars
- 13.1k
- Forks
- 1.1k
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 669
Description
`@astryx/no-raw-color` ([#5446](https://github.com/facebook/astryx/pull/5446))
ships at `warn` because there are 23 raw colours in component source today. All
23 are real — a colour written into a component is the colour every theme gets,
because a theme can retint any token a component reads but cannot reach inside a
literal.
They are not one cleanup. Each group wants a **token decision**, which is why
none of them was fixed alongside the rule:
### lab — `LogStream`, 10 hits
`LogStream.tsx:114-121, 278, 313` — a hardcoded dark console palette
(`#0a0a0a`, `#141417`, `#26262a`, `#8b8b94`, `#b9b9c0`, `#e8e8ea`, `#f2c00b`,
`#ff6166`, `#0e0e10`, `#1d1d21`). A log viewer that stays dark in a light theme
may well be the intent, but right now no theme can say otherwise. The decision
is whether this is a deliberately scheme-independent surface — in which case it
needs its own tokens — or a component that should follow the theme.
[#5445](https://github.com/facebook/astryx/pull/5445) (merged) parks
`LogStream`'s `levelWarn`/`levelError` on exactly this question: the token amber
and red are tuned for fills and miss 4.5:1 as small text, so moving them means
choosing a contrast-tuned status-text token, and lab stays at `warn` for
`no-light-dark-outside-theme` until it is answered. **Settle that first** — the
answer covers `warn`/`error` here too.
### lab — `Sankey`, 9 hits · charts — `dotGLInteractive`, 1 hit
`SankeyLabel.tsx:54, 55, 58, 59, 156, 203, 213, 225`,
`SankeyGrid.tsx:44, 56`, `dotGLInteractive.tsx:565` — all the same shape, a
`var(--token, #hex)` fallback. The token is right; the fallback is a raw colour
that paints if the stylesheet has not loaded.
`packages/core/src/reset.css:291` — `var(--color-text-secondary, #9ca3af)` — is
the same shape and rides with them. The lint rule cannot see it (ESLint never
parses a `.css` file), so it will not appear in the count; fix it in the same
pass.
One decision covers all eleven: **do we keep defensive fallbacks on core tokens
at all?** Every one of these tokens is declared unconditionally in
`theme/tokens.stylex.ts`, so the fallback is unreachable in a correctly loaded
app — and when it *is* reachable, an unstyled flash is arguably better than a
grey that belongs to no theme. If the answer is "drop them", it is a
ten-line change. If it is "keep them", the rule wants a narrow exemption for a
`var()` fallback and this issue closes.
### core, 2 hits
- `useChatDictation.ts:360` — `'var(--color-text-disabled, #999)'` on an inline
style. Same fallback question as `Sankey`.
- `ChatDictationButton.tsx:136` —
`hsl(calc(var(--accent-hue, 210) + ${hueShift}), 80%, 50%)`, the bar colour
when input clips. The hue shifts off an accent var but the saturation,
lightness and the fallback hue are fixed, so a theme whose accent is
desaturated gets an 80%-saturated clip colour that belongs to nothing else on
screen. Wants a token for "clipping/over-level", which is a design decision —
`StatusDot` and `Badge` may already have the vocabulary.
### Out of scope for the rule today — CLI templates, 194 hits
`packages/cli/assets/templates/**` is linted (`eslint.config.js:446`) but
`@astryx/no-raw-color` is not enabled there. Enable it and it reports **194** —
102 in `blocks`, 92 in `pages`.
That is its own decision and deliberately not folded into the rule's rollout.
These templates are scaffolded into a consumer's app, so a raw colour in one
teaches the wrong thing and lands in real code; but a large share of the 194 are
showcase content demonstrating a colour on purpose, which the rubric's T1
exceptions note treats as legitimate. Somebody has to read them before the rule
points at them.
### Order
`Sankey`/`dotGLInteractive`/`useChatDictation` (one decision, ten sites) is the
cheapest and is independent. `LogStream` waits on
[#5445](https://github.com/facebook/astryx/pull/5445).
`ChatDictationButton` needs a design call.
As each package reaches zero, promote it from `warn` to `error` in
`eslint.config.js` — the same path `no-physical-properties` took. The severity
comments in `eslint.config.js` and `internal/eslint-plugin-astryx/index.js` say
so at the point of change.
Reproduce the list with:
```
ASTRYX_STRICT_LINT=1 pnpm exec eslint packages/{core,lab,charts,richtext,vega}/src \
-f json | jq -r '.[].messages[] | select(.ruleId=="@astryx/no-raw-color")'
```
Contributor guide
Assessment
This issue has not been assessed yet.