From e13d93a3ed2a2e3b26e2387d97f1f5619dba63c5 Mon Sep 17 00:00:00 2001 From: npeter83 Date: Fri, 25 Sep 2026 17:04:08 +0200 Subject: [PATCH] fix(design): a toggle is `pressed`, never a bare aria-pressed; static labels are flat Badges with a tone, edged label spans lint-refused (E28) --- docs/DESIGN.md | 6 +++- frontend/eslint.config.js | 16 +++++++++ frontend/src/components/AdminLogs.tsx | 4 +-- frontend/src/components/AdminUsers.tsx | 27 +++------------ frontend/src/components/Channels.tsx | 7 ++-- frontend/src/components/PaletteLauncher.tsx | 4 +-- frontend/src/components/SettingsPanel.tsx | 9 ++--- frontend/src/components/ui/Badge.tsx | 14 ++++++-- .../src/components/ui/Button.dom.test.tsx | 3 ++ frontend/src/components/ui/Button.tsx | 6 +++- .../src/components/ui/IconButton.dom.test.tsx | 4 +++ frontend/src/components/ui/IconButton.tsx | 6 +++- frontend/src/design-lab/batchA.tsx | 1 + frontend/src/design-lab/batchB.tsx | 6 ++-- frontend/src/design-lab/batchC.tsx | 1 + frontend/src/index.css | 4 ++- .../src/lib/hoverAndLink.contract.test.ts | 34 +++++++++++++++++++ frontend/src/lib/theme.contract.test.ts | 5 +++ 18 files changed, 113 insertions(+), 44 deletions(-) diff --git a/docs/DESIGN.md b/docs/DESIGN.md index 62c1cc89..c0a81e19 100644 --- a/docs/DESIGN.md +++ b/docs/DESIGN.md @@ -190,7 +190,10 @@ Also in force: a role would replace both and is a lint error too — a field that floats takes `shadow-float`, the same shadow. - **Static vs pressable (owner, S3d):** a label that does nothing (a topic, a keyword, a status, a count) is a flat, tonal `Badge` with no edge; everything that does something has an edge (a chip, a trigger, a field). - A genre that filters the library is a chip; the same genre where it can't is a badge. + A genre that filters the library is a chip; the same genre where it can't is a badge. A badge's `tone` + (neutral / accent / warn) is its own colour at 6%, measured at 4.5:1 in every scheme; a `` drawn with a + round edge is a lint error (F29). A toggle button states itself through `pressed` (the solid accent), never a + bare `aria-pressed`, which the type refuses (F28). - **A link that looks like a button** (a download, a sign-in that leaves the app) is `LinkButton` / `IconLink`: still an ``, wearing the button's own face. - **Page chrome (B4):** a page's tabs and filters sit in ONE sticky band of the page colour, with the fade @@ -373,5 +376,6 @@ Wherever there is text, the user can select it and copy it, and no click action | 2026-09-25 | Edges and hovers (F14) | The ≥ 3:1 edge on the field family (fields, the form trigger); labelled pills keep the faint edge and the accent-edge hover | The ≥ 3:1 edge and a state-layer hover on every control | 1.4.11 asks an edge only where nothing else identifies the control; a heavy edge on every chip and tab weighs the whole UI down | | 2026-09-25 | Rating and live (F16) | Own tokens: `--rating` (theme-scoped gold), `--live`/`--live-fg`, `--rating-media`, `--media-chrome`; palette classes lint-refused | Map them to `--warn` / `--danger` | A gold star and a red LIVE are what the eye expects; as warn/danger they would read as a status. The old amber score was 2:1 on light | | 2026-09-25 | Fjord trial (B2 exception) | A fifth scheme, temporary: Midnight's neutrals, Playnite's steel accent (#337599 lifted to #5aa1cb) and steel rules; exit = fold into Midnight or remove | Retune Midnight straight away; borrow only the qualities | The owner wants to live with the calmer palette app-wide before it replaces the default; it breaks "own hue family" on purpose, and only until that call | +| 2026-09-25 | Badge tones (F29) | `Badge tone` neutral / accent / warn at 6%; light `--warn` #b45309 → #a14a07; edged label spans lint-refused | Keep edged status pills (a private Badge in Users, Settings "Granted", the suggestions count) | Edged = pressable at a glance; amber-700 was 4.58:1 as text and fell under 4.5 on its own tint | | 2026-09-24 | Chip family | One `Chip` (filter / token / tag / suggest / ghost) + `DismissibleChip`; nothing under 24; the lint rule "no raw ` + {/* @ts-expect-error a toggle states itself through `pressed`, which also paints it (B3) */} + + , ); expect(screen.getByRole("button", { name: "by label" })).toBeTruthy(); diff --git a/frontend/src/components/ui/Button.tsx b/frontend/src/components/ui/Button.tsx index 123e8e25..83317399 100644 --- a/frontend/src/components/ui/Button.tsx +++ b/frontend/src/components/ui/Button.tsx @@ -15,7 +15,9 @@ import { buttonClass, isLinkVariant, type ButtonSize, type ButtonVariant } from // No focus-visible here on purpose: @layer base in index.css already rings every