Summary
CustomTooltip paints a fixed dark surface in both light and dark mode, but anything rendered inside it styles itself from the ambient theme. On a light-mode page that means light-theme content on a near-black chip. Any theme-derived colour placed in a tooltip is therefore wrong in one of the two modes, and nothing in the component or the types says so.
The mechanism
src/custom/CustomTooltip/customTooltip.tsx sets the surface from literals, not from the palette:
bgColor = '#141414', // default parameter
...
tooltip: {
sx: {
background: bgColor,
color: WHITE,
...
#141414 and WHITE do not vary with palette.mode, so the chip is dark on every page. But a child element that resolves theme.palette.* gets the page's theme, which in light mode is tuned for a light background. The tooltip is effectively a dark-surface island with no corresponding theme context, and children have no way to know they are on one.
How it surfaced
Found while fixing an unrelated MUI 9 migration in CollaboratorAvatarGroup (#1780). That call site had been passing a surface override through componentsProps, which MUI 9 no longer reads, so the override had been silently dead since the MUI 9 bump. Removing it - the correct fix, since the surface belongs to CustomTooltip and none of the other call sites overrides it - made the inherited dark chip live again, and immediately exposed the real problem:
The <Divider /> inside that tooltip, separating the collaborator's name from the "Open Recents" button, is invisible in light mode. sistent never overrides palette.divider, so it falls through to MUI's mode-dependent defaults (createPalette.js): rgba(0,0,0,0.12) in light and rgba(255,255,255,0.12) in dark. Black at 12% opacity over #141414 is not visible. In dark mode it is fine.
The outlined Button in the same tooltip happens to escape it, because sistent maps primary to Colors.KEPPEL in both modes and that reads acceptably against dark.
That is the shape of the bug: whether a given tooltip looks right in light mode is currently a coincidence of which tokens its content happens to use.
Why this is a component-level defect, not a call-site one
There are 34 <CustomTooltip> usages across 27 files today. Every one of them is exposed the moment its content uses a mode-dependent token; the collaborator tooltip is simply the first with a Divider in it. Fixing it per call site means:
- each fix is invisible to the next author, so the trap resets every time;
- the palette lookups look correct in review -
theme.palette.divider is exactly what you would write - and only fail visually, in one mode, inside one component;
- there is no type or lint signal, because nothing distinguishes "inside a tooltip" from anywhere else.
Suggested resolution
Have CustomTooltip establish the theme context its surface implies, rather than only painting the surface - e.g. wrap its content in a ThemeProvider carrying a dark-mode palette (or the sistent dark theme), so palette.divider, text.* and friends resolve against the surface the content is actually on. Then a Divider in a tooltip is correct without the author having to know.
Two details worth settling in that change:
bgColor is a public prop, so a caller can pass a light surface. The context should follow the actual surface rather than being hardcoded to dark, or bgColor should be narrowed.
color: WHITE on the tooltip root is doing the same job by brute force for text only; it should probably fall out of the context rather than being set separately.
Deliberately not in scope: overriding palette.divider globally in sistent's theme. That would change every Divider in every consumer to fix a tooltip.
Interim state
#1780 takes the narrow fix - styling the affected content correctly for the dark surface at that one call site, with a comment linking here - so nothing visibly broken ships while this waits. That call-site workaround should be removed as part of the component-level fix.
Summary
CustomTooltippaints a fixed dark surface in both light and dark mode, but anything rendered inside it styles itself from the ambient theme. On a light-mode page that means light-theme content on a near-black chip. Any theme-derived colour placed in a tooltip is therefore wrong in one of the two modes, and nothing in the component or the types says so.The mechanism
src/custom/CustomTooltip/customTooltip.tsxsets the surface from literals, not from the palette:#141414andWHITEdo not vary withpalette.mode, so the chip is dark on every page. But a child element that resolvestheme.palette.*gets the page's theme, which in light mode is tuned for a light background. The tooltip is effectively a dark-surface island with no corresponding theme context, and children have no way to know they are on one.How it surfaced
Found while fixing an unrelated MUI 9 migration in
CollaboratorAvatarGroup(#1780). That call site had been passing a surface override throughcomponentsProps, which MUI 9 no longer reads, so the override had been silently dead since the MUI 9 bump. Removing it - the correct fix, since the surface belongs toCustomTooltipand none of the other call sites overrides it - made the inherited dark chip live again, and immediately exposed the real problem:The
<Divider />inside that tooltip, separating the collaborator's name from the "Open Recents" button, is invisible in light mode. sistent never overridespalette.divider, so it falls through to MUI's mode-dependent defaults (createPalette.js):rgba(0,0,0,0.12)in light andrgba(255,255,255,0.12)in dark. Black at 12% opacity over#141414is not visible. In dark mode it is fine.The outlined
Buttonin the same tooltip happens to escape it, because sistent mapsprimarytoColors.KEPPELin both modes and that reads acceptably against dark.That is the shape of the bug: whether a given tooltip looks right in light mode is currently a coincidence of which tokens its content happens to use.
Why this is a component-level defect, not a call-site one
There are 34
<CustomTooltip>usages across 27 files today. Every one of them is exposed the moment its content uses a mode-dependent token; the collaborator tooltip is simply the first with aDividerin it. Fixing it per call site means:theme.palette.divideris exactly what you would write - and only fail visually, in one mode, inside one component;Suggested resolution
Have
CustomTooltipestablish the theme context its surface implies, rather than only painting the surface - e.g. wrap its content in aThemeProvidercarrying a dark-mode palette (or the sistent dark theme), sopalette.divider,text.*and friends resolve against the surface the content is actually on. Then aDividerin a tooltip is correct without the author having to know.Two details worth settling in that change:
bgColoris a public prop, so a caller can pass a light surface. The context should follow the actual surface rather than being hardcoded to dark, orbgColorshould be narrowed.color: WHITEon the tooltip root is doing the same job by brute force for text only; it should probably fall out of the context rather than being set separately.Deliberately not in scope: overriding
palette.dividerglobally in sistent's theme. That would change everyDividerin every consumer to fix a tooltip.Interim state
#1780 takes the narrow fix - styling the affected content correctly for the dark surface at that one call site, with a comment linking here - so nothing visibly broken ships while this waits. That call-site workaround should be removed as part of the component-level fix.