Bug: Avatar's fallback initials use --color-text-secondary on --color-neutral, which fails WCAG AA contrast (4.5:1 for normal text) in dark mode, though it passes comfortably in light mode.
Evidence
Computed contrast (relative luminance per WCAG, --color-neutral composited over its typical surface background):
| Theme |
Effective background |
Text color |
Contrast |
AA (4.5:1)? |
| Light |
rgb(230, 235, 238) (--color-neutral @ 0.1 alpha over --color-background-surface #FFFFFF) |
--color-text-secondary #4E606F |
5.42:1 |
Pass |
| Dark |
rgb(69, 70, 73) (--color-neutral @ 0.2 alpha over --color-background-surface #1F1F22) |
--color-text-secondary #AAAFB5 |
4.27:1 |
Fail |
For reference, --color-text-primary on the same dark background computes to 7.25:1 (comfortable pass), and 15.63:1 in light mode.
Where this surfaces
packages/core/src/Avatar/Avatar.tsx, the fallback style block (initials + default icon surface): backgroundColor: colorVars['--color-neutral'], color: colorVars['--color-text-secondary'].
Found while reviewing #4327, which briefly switched this to --color-text-primary to fix the dark-mode failure, but that also changes light mode's already-passing appearance for every existing avatar (light mode goes from 5.42:1 to 15.63:1, a much starker text weight than the rest of the design intends for secondary/muted surfaces). That change was reverted out of #4327 as out of scope, pending a proper fix here.
Open question for whoever picks this up
Two directions, worth a maintainer call before implementing:
- Component-local: give
Avatar's fallback surface a theme-aware color (e.g. light-dark(var(--color-text-secondary), var(--color-text-primary)) or similar), keeping other consumers of --color-text-secondary on --color-neutral untouched.
- Token-level: if
--color-text-secondary's dark value is under-contrasted against --color-neutral specifically (not necessarily other neutral-adjacent surfaces), it may be worth checking whether other components pairing these same two tokens have the identical dark-mode gap, in which case a token-level fix might be the more correct scope.
I didn't check every other consumer of this exact token pairing, so I can't say how widespread it is beyond Avatar.
Bug:
Avatar's fallback initials use--color-text-secondaryon--color-neutral, which fails WCAG AA contrast (4.5:1 for normal text) in dark mode, though it passes comfortably in light mode.Evidence
Computed contrast (relative luminance per WCAG,
--color-neutralcomposited over its typical surface background):rgb(230, 235, 238)(--color-neutral@ 0.1 alpha over--color-background-surface#FFFFFF)--color-text-secondary#4E606Frgb(69, 70, 73)(--color-neutral@ 0.2 alpha over--color-background-surface#1F1F22)--color-text-secondary#AAAFB5For reference,
--color-text-primaryon the same dark background computes to 7.25:1 (comfortable pass), and 15.63:1 in light mode.Where this surfaces
packages/core/src/Avatar/Avatar.tsx, thefallbackstyle block (initials + default icon surface):backgroundColor: colorVars['--color-neutral'],color: colorVars['--color-text-secondary'].Found while reviewing #4327, which briefly switched this to
--color-text-primaryto fix the dark-mode failure, but that also changes light mode's already-passing appearance for every existing avatar (light mode goes from 5.42:1 to 15.63:1, a much starker text weight than the rest of the design intends for secondary/muted surfaces). That change was reverted out of #4327 as out of scope, pending a proper fix here.Open question for whoever picks this up
Two directions, worth a maintainer call before implementing:
Avatar's fallback surface a theme-aware color (e.g.light-dark(var(--color-text-secondary), var(--color-text-primary))or similar), keeping other consumers of--color-text-secondaryon--color-neutraluntouched.--color-text-secondary's dark value is under-contrasted against--color-neutralspecifically (not necessarily other neutral-adjacent surfaces), it may be worth checking whether other components pairing these same two tokens have the identical dark-mode gap, in which case a token-level fix might be the more correct scope.I didn't check every other consumer of this exact token pairing, so I can't say how widespread it is beyond
Avatar.