Skip to content

Avatar fallback initials fail WCAG AA contrast in dark mode (--color-text-secondary on --color-neutral) #5279

Description

@HelloOjasMutreja

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions