fix(a11y): raise the target status-pill text contrast to AA

The status pill painted full-saturation Dracula green/orange/red text on
a 12-14% same-hue tint. That fails WCAG AA (4.5:1) for the out tone on
the muted insights reference panel in dark mode (3.87:1) and for every
tone on a white card in light mode (1.2-2.7:1), since the pill used the
raw Dracula palette rather than the theme-aware feedback tokens.

Switch the pill to dedicated theme-aware tokens (status-pill-in/near/out)
and a 10% tint: dark mode keeps Dracula green/orange and lifts the out
tone off #ff5555 to a lighter red; light mode adopts the darker
AA-corrected family already used for the chart and destructive colours.
All three tones now clear 4.5:1 on both bg-card and bg-muted/30 in both
themes (worst case 4.62:1).
This commit is contained in:
Marc-André Bombeck committed 2026-06-01 21:17:09 +02:00
1 parent 0b10932c53
commit 6a2762ec35
2 files changed
+44 -3

No files matched your search

+33
View File
@@ -97,6 +97,18 @@
--color-success: var(--success);
--color-warning: var(--warning);
--color-info: var(--info);
/*
* Status-pill text tokens. The target status pill paints coloured text
* on a 10% same-hue tint; the raw Dracula green/orange/red would fail
* WCAG AA (4.5:1) for the "out" tone on the muted reference panel in
* dark mode and for every tone on a white card in light mode. These
* theme-aware tokens land each tone at or above AA on both `bg-card`
* and `bg-muted/30` in both themes while keeping the Dracula feel.
*/
--color-status-pill-in: var(--status-pill-in);
--color-status-pill-near: var(--status-pill-near);
--color-status-pill-out: var(--status-pill-out);
}
/*
@@ -167,6 +179,16 @@
--sidebar-border: #44475a;
--sidebar-ring: #bd93f9;
/*
* Status-pill text in dark mode. "in" / "near" keep the Dracula
* green / orange (both clear AA on the muted panel); "out" lifts off
* the raw `#ff5555`, which lands at 3.99:1 on `bg-muted/30`, to a
* lighter Dracula red that clears 4.5:1 on both card and panel.
*/
--status-pill-in: #50fa7b;
--status-pill-near: #ffb86c;
--status-pill-out: #ff8a8a;
color-scheme: dark;
}
@@ -212,6 +234,17 @@
--sidebar-border: #cfcfde;
--sidebar-ring: #644ac9;
/*
* Status-pill text in light mode (Alucard). The bright Dracula
* green / orange / red read 1.2–2.7:1 on a near-white tint; these
* darker tones — the same family already used for `--success` /
* `--warning` / the light-mode reds — clear AA on both the white card
* and the muted reference panel.
*/
--status-pill-in: #14720a;
--status-pill-near: #a34d14;
--status-pill-out: #b32d1e;
color-scheme: light;
}
+11 -3
View File
@@ -148,6 +148,14 @@ export function statusGroupForCategory(
return "near";
}
// Coloured text on a 10% same-hue tint with a 30% ring. The tint and
// text share one theme-aware token per tone (`--status-pill-{in,near,
// out}` in globals.css) so the pill clears WCAG AA (4.5:1) on both the
// Targets card (`bg-card`) and the W5 insights reference panel
// (`bg-muted/30`) in both dark and light themes — the raw Dracula
// green/orange/red failed AA for the "out" tone on the muted panel in
// dark mode and for every tone on a white card in light mode.
//
// Use the Tailwind v4 parenthesised CSS-variable shorthand
// (bg-VAR-PAREN-FORM-/N) instead of the legacy bracketed VAR-form. The
// bracketed form combined with an opacity modifier emits an escaped
@@ -158,9 +166,9 @@ export function statusGroupForCategory(
// that parses cleanly. See the Tailwind v4 upgrade guide for the
// migration from bracket-form to paren-form for CSS-variable values.
export const STATUS_PILL_STYLES: Record<"in" | "near" | "out", string> = {
in: "bg-(--dracula-green)/12 text-(--dracula-green) ring-(--dracula-green)/30",
near: "bg-(--dracula-orange)/14 text-(--dracula-orange) ring-(--dracula-orange)/30",
out: "bg-(--dracula-red)/12 text-(--dracula-red) ring-(--dracula-red)/30",
in: "bg-(--status-pill-in)/10 text-(--status-pill-in) ring-(--status-pill-in)/30",
near: "bg-(--status-pill-near)/10 text-(--status-pill-near) ring-(--status-pill-near)/30",
out: "bg-(--status-pill-out)/10 text-(--status-pill-out) ring-(--status-pill-out)/30",
};
export interface TargetStatusPillProps {