From 5c499e1e38e1e9e8948e0d23532f63bd316204f8 Mon Sep 17 00:00:00 2001 From: Eelco Hillenius Date: Sat, 15 Aug 2026 18:32:37 -0700 Subject: [PATCH] fix(passage): let the stimulus tabs follow the theme PIE-818 The paired-passage tabs stayed white with black ink on every color scheme while the passage body beneath them went dark, because the tab fill, the tab ink and the selection indicator came from MUI's palette (`theme.palette.common.white` / `.black`), which does not follow `--pie-*`. They now read `color.background()` and `color.text()` from `@pie-lib/render-ui`, which resolve to `var(--pie-background, ...)` and `var(--pie-text, ...)` -- the same tokens the passage body already uses, so the tab now carries the colour of the panel it opens. The two `#D9DADA` borders -- the tab outline and the strip's bottom rule -- become `color.borderGray()`. The literal measured roughly 1.2:1 against the dark schemes' surfaces, and the tab outline is the only thing separating an unselected tab from the strip, so it was effectively absent exactly where it did the most work. `--pie-border-gray` is stepped to the 3:1 non-text minimum in every built-in scheme. The strip behind the tabs keeps a host-supplied `--pie-passage-header-background` unchanged on every scheme, which is deliberate: Knowledge Checks' pale green-blue is a client decision and not a scheme's business to override. What changes is the no-host fallback, from a white literal to `color.backgroundDark()`, so the strip follows the theme instead of staying white over a dark body. That covers hosts which never opt in, including the section player when its own card-header token is unset. Both `theme.palette.common.*` lines carried "replace with color.background() once PD-2801 is DONE". PD-2801 is about adding background styling to OT's `color-contrast` class -- the mechanism pie-theme superseded -- and has been Blocked since 2023, so it no longer gates this. Not changed: the selected indicator stays `color.tertiary()` and the MUI indicator bar stays `color.white()`. Both already resolve through tokens every scheme sets, `--pie-white` being remapped to the scheme's own background rather than to white. --- packages/passage/src/stimulus-tabs.jsx | 43 +++++++++++++++++++++----- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/packages/passage/src/stimulus-tabs.jsx b/packages/passage/src/stimulus-tabs.jsx index eab59fe6a9..044fc67c5b 100644 --- a/packages/passage/src/stimulus-tabs.jsx +++ b/packages/passage/src/stimulus-tabs.jsx @@ -79,12 +79,26 @@ const PassageAuthor = styled('div')({ }); const TabStyled = styled(Tab)(({ theme }) => ({ - background: theme.palette.common.white, // replace with color.background() once PD-2801 is DONE + /* + * The tab carries the colour of the panel it opens, which is what makes it read as a + * tab rather than a button, and it has to be the themed panel colour: MUI's palette + * does not follow `--pie-*`, so `common.white` here left the tab white on every color + * scheme while the passage body beneath it went dark. The comment this replaces gated + * the change on PD-2801, which is about OT's `color-contrast` class -- the mechanism + * pie-theme superseded, and blocked since 2023. + */ + background: color.background(), fontSize: 'inherit', fontFamily: 'Roboto, sans-serif', - color: theme.palette.common.black, // remove when PD-2801 is DONE + color: color.text(), borderRadius: `${theme.spacing(2)} ${theme.spacing(2)} 0 0`, - border: '1px solid #D9DADA', + /* + * `--pie-border-gray` is stepped to the 3:1 non-text minimum in every scheme. The + * literal it replaces measured about 1.2:1 against the dark schemes' surfaces, so the + * tab outline -- the only thing separating an unselected tab from the strip -- was + * invisible there. + */ + border: `1px solid ${color.borderGray()}`, borderBottomWidth: 0, minHeight: '56px', padding: '8px 10px', @@ -106,7 +120,7 @@ const TabStyled = styled(Tab)(({ theme }) => ({ }, '&.Mui-selected': { - color: theme.palette.common.black, + color: color.text(), '.passage-label': { opacity: 1, }, @@ -126,11 +140,16 @@ const TabStyled = styled(Tab)(({ theme }) => ({ }, })); -const Underline = styled('div')(({ theme }) => ({ +/* + * The selection indicator, one per tab. Unselected it has to disappear into the tab, so it + * paints the tab's own background rather than a fixed white; selected it becomes + * `--pie-tertiary`, which every scheme sets. + */ +const Underline = styled('div')(() => ({ height: '2px', width: '100%', marginTop: '6px', - background: theme.palette.common.white, // replace with color.background() once PD-2801 is DONE + background: color.background(), })); class StimulusTabs extends React.Component { @@ -381,8 +400,16 @@ class StimulusTabs extends React.Component { // so the reclaimed space flows to the passage content below. zoom: zoomCompensation, '& .MuiTabs-list': { - backgroundColor: 'var(--pie-passage-header-background, #ffffff)', - borderBottom: '1px solid #D9DADA', + /* + * The strip behind the tabs. A host that has opted into + * `--pie-passage-header-background` keeps its own colour on every + * scheme -- Knowledge Checks' pale green-blue is deliberate and is not + * a scheme's business to override. With no host colour the fallback has + * to be a theme token rather than a white literal, or the strip stays + * white over a dark passage body. + */ + backgroundColor: `var(--pie-passage-header-background, ${color.backgroundDark()})`, + borderBottom: `1px solid ${color.borderGray()}`, }, '& .MuiTabs-indicator': { backgroundColor: color.white(),