From fc186e1230b3bc8013ad92cd9a1541fe3fdb9c04 Mon Sep 17 00:00:00 2001 From: npeter83 Date: Tue, 11 Aug 2026 04:20:10 +0200 Subject: [PATCH] =?UTF-8?q?refactor(ui):=20address=20/code-review=20on=20.?= =?UTF-8?q?btn-primary=20=E2=80=94=20tone=20family=20+=20doc=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Generalize the recipe into a .btn-{tone} family: add .btn-danger / .btn-warn siblings sharing one hover-dim, and migrate the two hand-rolled tone-action buttons (ConfirmProvider danger confirm, Banner warning action) onto them, so primary/danger/warn action paints can't drift. - Reword the recipe comment: it owns paint + one standard hover-dim (not 'PAINT-ONLY' — that mislabel obscured the hover behaviour). - Drop the now-redundant hover:opacity-90 from Banner's action-button base (each tone's recipe supplies the hover). The 3 previously hover-less primary buttons keep the standard hover-dim gained in the prior commit (intentional consistency; now accurately documented). Gate green (tsc/eslint-0/prettier/knip/vitest 79); self-E2E confirmed btn-danger/btn-warn compute to their tone/tone-fg tokens. --- frontend/src/components/Banner.tsx | 4 ++-- frontend/src/components/ConfirmProvider.tsx | 2 +- frontend/src/index.css | 23 +++++++++++++++------ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/Banner.tsx b/frontend/src/components/Banner.tsx index e0fae05f..ecdc536d 100644 --- a/frontend/src/components/Banner.tsx +++ b/frontend/src/components/Banner.tsx @@ -13,7 +13,7 @@ const TONES: Record = warning: { bar: "bg-warn/15 border-warn/30", icon: "text-warn", - action: "bg-warn text-warn-fg hover:opacity-90", + action: "btn-warn", }, }; @@ -42,7 +42,7 @@ export default function Banner({ {action && ( diff --git a/frontend/src/components/ConfirmProvider.tsx b/frontend/src/components/ConfirmProvider.tsx index 84150ec9..6051ff53 100644 --- a/frontend/src/components/ConfirmProvider.tsx +++ b/frontend/src/components/ConfirmProvider.tsx @@ -116,7 +116,7 @@ export function ConfirmProvider({ children }: { children: ReactNode }) { onClick={() => close(c.id)} className={`px-4 py-2 rounded-lg text-sm font-semibold transition ${ multi ? "w-full" : "" - } ${c.danger ? "bg-danger text-danger-fg hover:opacity-90" : "btn-primary"}`} + } ${c.danger ? "btn-danger" : "btn-primary"}`} > {c.label || t("common.confirm")} diff --git a/frontend/src/index.css b/frontend/src/index.css index 9fce8e50..4f69c0c5 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -496,16 +496,27 @@ body { color: var(--accent-fg); border-color: var(--accent); } - /* .btn-primary — the primary/ACTION button paint (solid accent). Distinct from the selection - recipes above: this is "the primary action", not "selected among options". PAINT-ONLY like - .chip-solid — a site keeps its own geometry (padding/radius/font/gap/disabled:opacity/transition). - Migrated sites MUST drop `bg-accent text-accent-fg hover:opacity-90` so this @layer-components - rule isn't beaten by those utilities. No focus-visible — @layer base already rings every button. */ + /* .btn-{tone} — solid ACTION-button paint (the "primary/danger/warn action", distinct from the + selection recipes above which are "selected among options"). Each sets its tone fill + contrasting + fg; all share ONE standard hover-dim. Like .chip-solid this owns paint (+ that single hover + behaviour), NOT geometry — a site keeps its own padding/radius/font/gap/disabled:opacity/shadow. + Migrated sites MUST drop `bg-{tone} text-{tone}-fg hover:opacity-90` so these @layer-components + rules aren't beaten by those utilities. No focus-visible — @layer base already rings every button. */ .btn-primary { background-color: var(--accent); color: var(--accent-fg); } - .btn-primary:hover:not(:disabled) { + .btn-danger { + background-color: var(--danger); + color: var(--danger-fg); + } + .btn-warn { + background-color: var(--warn); + color: var(--warn-fg); + } + .btn-primary:hover:not(:disabled), + .btn-danger:hover:not(:disabled), + .btn-warn:hover:not(:disabled) { opacity: 0.9; } }