MUI's palette does not follow `--pie-*`, so every `theme.palette.grey[N]` read held a
fixed hex under every colour scheme. Measured against each scheme's own
`--pie-background`, shades 100-500 fall below the 3:1 non-text minimum in six of the ten
schemes and 600-800 in three or four. The answer-choice separator George reported --
grey[300] at about 1.1:1 on black-on-rose, which sets `--pie-border` to #000000 -- is
the visible end of that, not a special case: none of these reads were correct.
Each site takes the accessor matching its role, since the roles differ and so do the
contrast requirements:
- strokes, dividers and connectors -> `color.border()`, at least 3.23:1 against every
scheme's background. `--pie-border-light` was rejected: 1.53:1 in the default scheme.
- fills -> `color.backgroundDark()`; pressed or selected fills ->
`color.dropdownBackground()`, whose default #E0E1E6 matches what several of these
sites already used. A fill belongs close to the page, so the 3:1 floor is not its
job; the stroke on it carries the separation.
- text -> `color.text()`. No neutral token clears 4.5:1 in every scheme
(`--pie-border-gray` tops out at 3.17:1), so muted text has no scheme-following
option. The likert column header was the worst of these at 1.88:1 on white, failing
before any scheme was applied.
- interactive icons -> `color.text()`; de-emphasised non-text glyphs ->
`color.borderGray()`, where 3:1 is the bar.
- disabled affordances -> `color.disabled()`, whose default is the same `grey` literal
the math-inline remove button already used, so that one is unchanged at rest.
- heavy card strokes that were grey[700] -> `color.borderDark()`, #646464 against the
#616161 they replace.
Four surfaces move alongside their strokes. `palette.common.white` is MUI's #fff
regardless of scheme, so tokenising a stroke while leaving the surface fixed would put
a scheme's border colour on a permanently white card -- under white-on-black,
`--pie-border` is #ffffff, erasing the outline this was meant to fix. `--pie-white`
inverts with the scheme, which is what `common.white` was standing in for on the two
annotation popovers, the inline-dropdown menu item and the graphing tool spacer.
File-local grey literals in the same styled blocks move too, because they are the same
defect wearing a different spelling: graphing's `GREY_A100`/`GREY_A200`, the
drag-in-the-blank choice stroke and grip glyph, match-list's arrow head -- which had to
follow its own shaft or the arrow loses its point on a dark scheme -- the annotation
popover's pointer triangle, and the inline-dropdown toolbar's own #E0E1E6 surface.
`#C0C3CF` is `--pie-blue-grey-300`'s default, but that token is a fill measuring 1.00:1
against some backgrounds, so response-slot outlines take the stroke token.
`color.buttonFocusOutline()` is deliberately not used here: it is new in pie-lib and
the published `@pie-lib/render-ui` this repo resolves does not carry it yet. The two
focus rings that needed it are in pie-lib, where render-ui comes from the workspace.
The `row.test.jsx` render-ui mock gains `border`, the accessor answer-config-block now
calls. `choice-input.test.jsx` still fails on `color.keyBoardFocusIndicator` missing
from the installed render-ui; that predates this change.
What
theme.palette.grey[N] does not follow --pie-*, so every one of those reads held a
fixed hex under every colour scheme. This moves the 32 reads across twelve element
packages onto the color.*() accessors.
Part of PIE-856. Pairs with pie-framework/pie-lib#2310, which carries the eight
@pie-lib call sites and adds color.buttonFocusOutline(). Both need to land before
pie-elements-ng can sync the generated files.
Scope
Reported by George Schneiderman with screenshots: the answer-choice separator in
multiple-choice measures about 1.1:1 against the black-on-rose background, where that
scheme sets --pie-border to #000000.
That is one instance of a defect that covers all of them. Measured against each scheme's
own --pie-background across the ten schemes in pie-players —
packages/theme/src/color-schemes.css — MUI's grey shades 100–500 fall below the 3:1
non-text minimum in six of the ten, and 600–800 in three or four. Per site the worst case
ran between 1.01:1 and 1.72:1; it is now at least 3.17:1 everywhere.
Why these tokens
Roles differ and so do the contrast requirements, so sites take the accessor matching the
role rather than one replacement token. Strokes, dividers and connectors →
--pie-border (3.23:1 worst). Heavy card outlines → --pie-border-dark (5.62:1), whose
#646464 default is near the #616161 it replaces. Fills → --pie-background-dark, and
selected or pressed fills → --pie-dropdown-background, whose #E0E1E6 default matches
what several sites already used; a fill belongs close to the page, so the 3:1 floor is not
its job — the stroke on it carries the separation. Text → --pie-text, because no neutral
token clears 4.5:1 in every scheme (--pie-border-gray tops out at 3.17:1). Interactive
icons → --pie-text; quieter non-text glyphs → --pie-border-gray, where 3:1 is the bar.
Disabled affordances → --pie-disabled, whose default is the same grey literal the
math-inline remove button already used, so that one is unchanged at rest.
--pie-border-light is deliberately unused for strokes: it measures 1.53:1 in the default
scheme.
Why not remap palette.grey in the theme
That was the obvious alternative — one change in the theme instead of 32 at the call
sites — and it does not work. MUI 7.3.11's Tooltip evaluates
alpha(theme.palette.grey[700], 0.92) when its popper mounts and throws
MUI: Unsupported var(...) color; Tooltip appears in 21 files. AppBar
(getContrastText) and collapsed Breadcrumbs (emphasize) have the same hazard on
shades 100/200/600/900. Leaving MUI's own greys as real hex and moving the call sites
avoids all of it.
Surfaces that move with their strokes
Four palette.common.white surfaces become --pie-white: the two extended-text-entry
annotation popovers, the inline-dropdown menu item, and the graphing tool spacer.
common.white is MUI's #fff regardless of scheme, so tokenising a stroke while leaving
the surface fixed would put a scheme's border colour on a permanently white card — under
white-on-black --pie-border is #ffffff, erasing the outline this was meant to fix.
--pie-white inverts with the scheme, which is what common.white was standing in for.
Grey literals in the same styled blocks
Same defect, different spelling, so they move too: graphing's GREY_A100/GREY_A200,
the drag-in-the-blank choice stroke and grip glyph, match-list's arrow head — which
had to follow its own shaft or the arrow loses its point on a dark scheme — the annotation
popover's pointer triangle, and the inline-dropdown toolbar's own #E0E1E6 surface.
#C0C3CF is --pie-blue-grey-300's default, but that token is a fill measuring 1.00:1
against some backgrounds, so response-slot outlines take the stroke token.
Not touched: semantic accents (error.main, primary.main), the rgb(153,255,153) /
rgb(255,204,238) annotation highlights, and math-toolbar's #00bb00 — retinting a
brand accent is a design call, not this change.
Deliberately not used here
color.buttonFocusOutline() is new in pie-framework/pie-lib#2310 and the published
@pie-lib/render-ui this repo resolves (5.2.0-next.6) does not carry it yet. The two
focus rings that needed it live in pie-lib, where render-ui comes from the workspace.
Tests
The twelve touched packages: 80 suites, 1681 passing. eslint at exact parity with
develop — 0 errors, same 65 warnings, none new.
The row.test.jsx @pie-lib/render-ui mock gains border, the accessor
answer-config-block now calls. choice-input.test.jsx still fails on
color.keyBoardFocusIndicator missing from the installed render-ui; that predates this
change and reproduces on develop.
Visible change
Strokes that were #e0e0e0 or #bdbdbd now resolve to --pie-border, i.e. #8f8f8f in
the default light theme. Deliberate — those values were under 3:1 before any scheme was
applied — but worth a design look before this ships.