fix(design): the button and chip hover colours were never generated — an act: variant instead of a runtime prefix (E28)

buttonStyles/chipStyles glued the hover guard on at runtime (`${ACT}hover:text-fg`). Tailwind emits CSS
only for a class it finds whole in the source, so all 22 guarded hovers shipped with no rule: no text or
edge colour on hover for ghost/outline/danger buttons, no white layer on the player's control row, no
underline on a link button, no accent hover on token/suggest/ghost chips. The stylesheet had 0 rules
for `not-aria-disabled`.

- `@custom-variant act` (index.css): the same guard as the state layers; `:disabled` never matches an
  <a>, so one variant serves buttons and links and the per-element variant maps go.
- ui/tailwindScan.contract.test.ts: every class the primitives can emit stands whole in their source.
- a lint rule refuses a variant right after an interpolation; the `enabled:hover:` rule now points at
  `act:hover:`.
This commit is contained in:
2026-09-25 14:13:51 +02:00
parent ff80cc96fd
commit cc8e0648db
7 changed files with 144 additions and 48 deletions
+6 -5
View File
@@ -9,16 +9,17 @@ export type ChipSize =
| "sm" // 24, text-xs — a filter row
| "xs"; // 24, text-2xs, tight — a tag in a table row
const ACT = "enabled:not-aria-disabled:";
const PAINT: Record<ChipVariant, string> = {
// `.pill` owns the resting, hover AND pressed colours; a colour utility here would beat the pressed
// fill, so the open-popover state is the only one spelled out.
filter: "pill border shadow-xs aria-expanded:border-accent aria-expanded:text-accent",
token: `chip ${ACT}hover:border-accent ${ACT}hover:bg-accent/20 aria-expanded:border-accent`,
token: "chip act:hover:border-accent act:hover:bg-accent/20 aria-expanded:border-accent",
// B3: a filled control's hover mixes its own text colour into the fill, never an opacity dim.
tag: `chip-solid font-medium ${ACT}hover:bg-[color-mix(in_srgb,var(--accent-fg)_14%,var(--accent))]`,
suggest: `border border-dashed border-accent/50 text-accent/90 ${ACT}hover:text-accent ${ACT}hover:border-accent`,
ghost: `border border-dashed border-border text-muted ${ACT}hover:text-accent ${ACT}hover:border-accent`,
tag: "chip-solid font-medium act:hover:bg-[color-mix(in_srgb,var(--accent-fg)_14%,var(--accent))]",
suggest:
"border border-dashed border-accent/50 text-accent/90 act:hover:text-accent act:hover:border-accent",
ghost:
"border border-dashed border-border text-muted act:hover:text-accent act:hover:border-accent",
};
const SIZES: Record<ChipSize, string> = {