fix: gate the remaining text contrast failures behind High Contrast Mode (#27558)

Completes the contrast set after #27555, #27554 and the gray-500 branch, which between them cover text-gray-400, text-gray-500, dark:text-gray-600 and placeholders. This is everything still under 4.5:1 after those.

The grey scale in src/tailwind.css is achromatic oklch(L 0 0), so relative luminance is exactly L³. What is left:

- text-gray-300 dark:text-gray-700, the lightest muted pair, at 1.58:1 in light and 2.14:1 in dark. Used for inactive tab labels across the admin, workspace and playground layouts, breadcrumb separators and empty state hints. It resolves to gray-600 in light and gray-400 in dark.
- text-gray-400/70 on the embedded chat history dropdown icon, 2.07:1 against the 3:1 that WCAG 1.4.11 requires of icons.
- Hover states that land lighter than the new resting colour. Once the resting state is gray-600, an element hovering to gray-500 gets less readable on interaction rather than more, so hover and group-hover targets of gray-500 resolve to gray-800. Sidebar/Section.svelte and the citation modal links are the sites this affects.
- The autocompletion ghost text in src/app.css, hardcoded #a0a0a0, 2.65:1 in light. The dark canvas already passes.
- The shimmer used for loading text, a #b4b4b4 gradient clipped to the glyphs at 2.10:1 in light. There is no solid colour to raise, so with the setting on it renders as flat gray-700 text instead.

Everything above is gated on the existing High Contrast Mode setting and changes nothing when it is off. No markup is touched, so this is src/app.css only.

Deliberately left alone: disabled: variants, since WCAG 1.4.3 exempts inactive components; the FileNav breadcrumb ancestors, which are non-clickable; decorative folder icons; and text-gray-100, dark:text-gray-800 and dark:text-gray-900, which are inverse text on filled buttons and already high contrast against their own backgrounds. The ad-hoc dark:text-gray-800 pairs in ChannelModal.svelte and automations/+layout.svelte stay as they are; dark:text-gray-800 doubles as the inverse text on the white buttons in Message.svelte, ResponseMessage.svelte and UserMessage.svelte, so it cannot be remapped in CSS without breaking those.

Not fixed here, and a genuine follow-up: .hljs-comment in src/app.css is #616161, roughly 3:1 on the dark code background. It sits outside the Tailwind grey scale and needs a highlight.js theme override rather than a utility remap.

Verified in a browser against Tailwind's emitted rules and layer order: with the setting on, the lightest pair resolves to gray-600 in light and gray-400 in dark, the hover and group-hover targets to gray-800, ghost text to gray-600 and the shimmer to solid gray-700, while inverse button text and every dark hover variant stay where they are; with the setting off nothing changes in either theme.
This commit is contained in:
Classic298
2026-07-27 00:57:00 +02:00
committed by GitHub
parent 5b035ea52b
commit 1ac8ef7853
+34
View File
@@ -884,3 +884,37 @@ body {
html.high-contrast:not(.dark) :is(.app-muted, .app-icon-muted, .tiptap table) {
color: var(--color-gray-600);
}
/* High Contrast Mode: the lightest muted pair, 1.58:1 in light and 2.14:1 in dark.
text-gray-400/70 is an icon colour, so 1.4.11 governs it, and 2.07:1 misses that too. */
@layer utilities {
html:where(.high-contrast):not(:where(.dark)) :is(.text-gray-300, .text-gray-400\/70) {
color: var(--color-gray-600);
}
html:where(.high-contrast).dark .dark\:text-gray-700 {
color: var(--color-gray-400);
}
/* Hover states that land lighter than the new resting colour. */
html:where(.high-contrast):not(:where(.dark)) .hover\:text-gray-500:hover {
color: var(--color-gray-800);
}
html:where(.high-contrast):not(:where(.dark)) .group:hover .group-hover\:text-gray-500 {
color: var(--color-gray-800);
}
}
/* Autocompletion ghost text is 2.65:1 in light; the dark canvas already passes. */
html.high-contrast:not(.dark) .ai-autocompletion::after {
color: var(--color-gray-600);
}
/* The shimmer gradient is 2.10:1 in light, and clipping it to the text leaves no
solid colour to raise; render it as flat text instead. */
html.high-contrast:not(.dark) .shimmer {
background: none;
color: var(--color-gray-700);
-webkit-text-fill-color: var(--color-gray-700);
}