Fix high-contrast solid buttons in dark mode

The solid color rules in the Button, IconButton, and Badge variant
matrices had no highContrast condition, so a high-contrast solid element
matched both the base rule and the high-contrast rule. With
tailwind-variants/lite (no tailwind-merge) both classes are emitted, and
a static text-white from the base wins over the theme-aware text step.
That looked fine in light mode but left illegible white text on the
light step-12 background once dark mode was enabled.

Gate the base solid rules on highContrast:false so the self-contained
high-contrast rules are authoritative. The tinted variants are left as
is: their step-11/step-12 text both flip with the theme, so they are
never illegible.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-06-28 14:24:21 +02:00
parent 8bfcabd58d
commit 1bf476c2d8
3 changed files with 27 additions and 18 deletions

View File

@@ -47,12 +47,15 @@ export const badge = tv({
},
compoundVariants: [
// solid: filled step-9 background, white text (dark for light hues)
{ variant: "solid", color: "neutral", class: "bg-sand-9 text-white" },
{ variant: "solid", color: "gold", class: "bg-gold-9 text-white" },
{ variant: "solid", color: "red", class: "bg-red-9 text-white" },
{ variant: "solid", color: "green", class: "bg-green-9 text-white" },
{ variant: "solid", color: "amber", class: "bg-amber-9 text-amber-12" },
{ variant: "solid", color: "sky", class: "bg-sky-9 text-sky-12" },
// Gated on highContrast:false so the high-contrast rules below don't also
// apply (tailwind-variants/lite has no merge — both would emit and a static
// text-white would win, breaking dark mode).
{ variant: "solid", color: "neutral", highContrast: false, class: "bg-sand-9 text-white" },
{ variant: "solid", color: "gold", highContrast: false, class: "bg-gold-9 text-white" },
{ variant: "solid", color: "red", highContrast: false, class: "bg-red-9 text-white" },
{ variant: "solid", color: "green", highContrast: false, class: "bg-green-9 text-white" },
{ variant: "solid", color: "amber", highContrast: false, class: "bg-amber-9 text-amber-12" },
{ variant: "solid", color: "sky", highContrast: false, class: "bg-sky-9 text-sky-12" },
{ variant: "solid", color: "neutral", highContrast: true, class: "bg-sand-12 text-sand-1" },
{ variant: "solid", color: "gold", highContrast: true, class: "bg-gold-12 text-gold-1" },
{ variant: "solid", color: "red", highContrast: true, class: "bg-red-12 text-red-1" },

View File

@@ -62,12 +62,15 @@ export const button = tv({
},
compoundVariants: [
// ── solid: filled step-9 background, white text (dark for light hues) ──
{ variant: ["solid", "classic"], color: "neutral", class: "bg-sand-9 text-white hover:bg-sand-10" },
{ variant: ["solid", "classic"], color: "gold", class: "bg-gold-9 text-white hover:bg-gold-10" },
{ variant: ["solid", "classic"], color: "red", class: "bg-red-9 text-white hover:bg-red-10" },
{ variant: ["solid", "classic"], color: "green", class: "bg-green-9 text-white hover:bg-green-10" },
{ variant: ["solid", "classic"], color: "amber", class: "bg-amber-9 text-amber-12 hover:bg-amber-10" },
{ variant: ["solid", "classic"], color: "sky", class: "bg-sky-9 text-sky-12 hover:bg-sky-10" },
// Gated on highContrast:false so the high-contrast rules below don't also
// apply (tailwind-variants/lite has no merge — both would emit and a static
// text-white would win, breaking dark mode).
{ variant: ["solid", "classic"], color: "neutral", highContrast: false, class: "bg-sand-9 text-white hover:bg-sand-10" },
{ variant: ["solid", "classic"], color: "gold", highContrast: false, class: "bg-gold-9 text-white hover:bg-gold-10" },
{ variant: ["solid", "classic"], color: "red", highContrast: false, class: "bg-red-9 text-white hover:bg-red-10" },
{ variant: ["solid", "classic"], color: "green", highContrast: false, class: "bg-green-9 text-white hover:bg-green-10" },
{ variant: ["solid", "classic"], color: "amber", highContrast: false, class: "bg-amber-9 text-amber-12 hover:bg-amber-10" },
{ variant: ["solid", "classic"], color: "sky", highContrast: false, class: "bg-sky-9 text-sky-12 hover:bg-sky-10" },
// classic adds elevation over solid
{ variant: "classic", class: "shadow-2" },
// solid high-contrast: step-12 background, step-1 text

View File

@@ -56,12 +56,15 @@ export const iconButton = tv({
},
compoundVariants: [
// solid / classic
{ variant: ["solid", "classic"], color: "neutral", class: "bg-sand-9 text-white hover:bg-sand-10" },
{ variant: ["solid", "classic"], color: "gold", class: "bg-gold-9 text-white hover:bg-gold-10" },
{ variant: ["solid", "classic"], color: "red", class: "bg-red-9 text-white hover:bg-red-10" },
{ variant: ["solid", "classic"], color: "green", class: "bg-green-9 text-white hover:bg-green-10" },
{ variant: ["solid", "classic"], color: "amber", class: "bg-amber-9 text-amber-12 hover:bg-amber-10" },
{ variant: ["solid", "classic"], color: "sky", class: "bg-sky-9 text-sky-12 hover:bg-sky-10" },
// Gated on highContrast:false so the high-contrast rules below don't also
// apply (tailwind-variants/lite has no merge — both would emit and a static
// text-white would win, breaking dark mode).
{ variant: ["solid", "classic"], color: "neutral", highContrast: false, class: "bg-sand-9 text-white hover:bg-sand-10" },
{ variant: ["solid", "classic"], color: "gold", highContrast: false, class: "bg-gold-9 text-white hover:bg-gold-10" },
{ variant: ["solid", "classic"], color: "red", highContrast: false, class: "bg-red-9 text-white hover:bg-red-10" },
{ variant: ["solid", "classic"], color: "green", highContrast: false, class: "bg-green-9 text-white hover:bg-green-10" },
{ variant: ["solid", "classic"], color: "amber", highContrast: false, class: "bg-amber-9 text-amber-12 hover:bg-amber-10" },
{ variant: ["solid", "classic"], color: "sky", highContrast: false, class: "bg-sky-9 text-sky-12 hover:bg-sky-10" },
{ variant: "classic", class: "shadow-2" },
{ variant: ["solid", "classic"], color: "neutral", highContrast: true, class: "bg-sand-12 text-sand-1 hover:bg-sand-12" },
{ variant: ["solid", "classic"], color: "gold", highContrast: true, class: "bg-gold-12 text-gold-1 hover:bg-gold-12" },