What's wrong
ImGuiPaletteMapper chooses priorities that put several foreground/background pairs ImGui draws on top of each other at almost the same lightness. The worst case is text selection.
TextSelectedBg is mapped to (Alternate, High) (ThemeProvider.ImGui/ImGuiPaletteMapper.cs:94) and is fully opaque. In a focused InputText, ImGui fills the selection rectangle with that colour and then draws Text (Neutral, VeryHigh) on top of it. For comparison, ImGui's own default is translucent: (0.26, 0.59, 0.98, 0.35).
Contrast ratios from new ImGuiPaletteMapper().MapTheme(theme), measured over all 38 themes in ThemeRegistry.AllThemes at 9454d42:
| Pair (foreground on background) |
Mapping lines |
Lowest |
Median |
Themes below threshold |
Text on TextSelectedBg |
:94, :44 |
1.45 |
1.97 |
38 of 38 below 3:1 |
SliderGrab (Primary MediumLow) on FrameBg (Neutral Low) |
:70, :40 |
1.34 |
1.85 |
38 of 38 below 3:1 |
PlotLines (Alternate Medium) on FrameBg |
:82, :40 |
1.69 |
2.38 |
36 of 38 below 3:1 |
Text on FrameBgActive (Neutral Medium) |
:44, :42 |
2.37 |
3.27 |
38 of 38 below 4.5:1 |
Worst cases:
- VSCode Light: selected text is
#000000 on #4a005e, a ratio of 1.45, so it effectively disappears.
- Everforest Light: selected text is
#5c6a72 on #dc6902 (1.61), and the slider grab is #afc541 on #d8d8c8.
- Catppuccin Mocha: selected text is
#cdd6f4 on #b787aa (2.06).
WCAG sets 4.5:1 as the minimum for body text and 3:1 for non-text UI parts. The only contrast test today, MapTheme_TextContrastsWithWindowBackground, only asserts that Text and WindowBg are not identical.
Suggested fix
TextSelectedBg: map it to a low accent priority (VeryLow or Low, as Button does) and/or give it a translucent alpha, so Text keeps its contrast.
SliderGrab and PlotLines/PlotHistogram: move them toward the high-visibility end, the way CheckMark uses VeryHigh.
FrameBgActive: keep it near Low or MediumLow, so text inside an active frame stays readable.
Acceptance criteria
Add a test that iterates ThemeRegistry.AllThemes and asserts these minimums:
Text on TextSelectedBg and on FrameBgActive: at least 4.5:1.
SliderGrab, PlotLines and CheckMark on FrameBg: at least 3:1.
This is separate from #110, which covers ImGuiCol slots that are not mapped at all, and #114, which covers VeryHigh neutral tinting.
What's wrong
ImGuiPaletteMapperchooses priorities that put several foreground/background pairs ImGui draws on top of each other at almost the same lightness. The worst case is text selection.TextSelectedBgis mapped to(Alternate, High)(ThemeProvider.ImGui/ImGuiPaletteMapper.cs:94) and is fully opaque. In a focusedInputText, ImGui fills the selection rectangle with that colour and then drawsText(Neutral, VeryHigh) on top of it. For comparison, ImGui's own default is translucent:(0.26, 0.59, 0.98, 0.35).Contrast ratios from
new ImGuiPaletteMapper().MapTheme(theme), measured over all 38 themes inThemeRegistry.AllThemesat9454d42:TextonTextSelectedBgSliderGrab(Primary MediumLow) onFrameBg(Neutral Low)PlotLines(Alternate Medium) onFrameBgTextonFrameBgActive(Neutral Medium)Worst cases:
#000000on#4a005e, a ratio of 1.45, so it effectively disappears.#5c6a72on#dc6902(1.61), and the slider grab is#afc541on#d8d8c8.#cdd6f4on#b787aa(2.06).WCAG sets 4.5:1 as the minimum for body text and 3:1 for non-text UI parts. The only contrast test today,
MapTheme_TextContrastsWithWindowBackground, only asserts that Text and WindowBg are not identical.Suggested fix
TextSelectedBg: map it to a low accent priority (VeryLow or Low, asButtondoes) and/or give it a translucent alpha, soTextkeeps its contrast.SliderGrabandPlotLines/PlotHistogram: move them toward the high-visibility end, the wayCheckMarkuses VeryHigh.FrameBgActive: keep it near Low or MediumLow, so text inside an active frame stays readable.Acceptance criteria
Add a test that iterates
ThemeRegistry.AllThemesand asserts these minimums:TextonTextSelectedBgand onFrameBgActive: at least 4.5:1.SliderGrab,PlotLinesandCheckMarkonFrameBg: at least 3:1.This is separate from #110, which covers ImGuiCol slots that are not mapped at all, and #114, which covers VeryHigh neutral tinting.