Skip to content

fix(theming): move the grey palette reads onto --pie-* tokens PIE-856 - #3102

Merged
CarlaCostea merged 1 commit into
developfrom
fix/PIE-856-grey-palette-tokens
Aug 21, 2026
Merged

fix(theming): move the grey palette reads onto --pie-* tokens PIE-856#3102
CarlaCostea merged 1 commit into
developfrom
fix/PIE-856-grey-palette-tokens

Conversation

@chillenious

Copy link
Copy Markdown
Contributor

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.

site before after
multiple-choice answer separator 1.01:1 3.23:1
annotation popover strokes, match dividers 1.03:1 3.23:1
tile, response-area and button strokes 1.06:1 3.23:1
math-inline / math-templated card stroke 1.28:1 5.62:1
likert column header (text) 1.06:1 6.21:1

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.

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.
@chillenious
chillenious force-pushed the fix/PIE-856-grey-palette-tokens branch from e7efcb2 to d7d005b Compare August 20, 2026 05:35
@CarlaCostea
CarlaCostea merged commit 31b2e2a into develop Aug 21, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants