From f52370737606b08304d93716ddad1a1df16dcbeb Mon Sep 17 00:00:00 2001 From: holo Date: Mon, 20 Apr 2026 22:50:53 +0800 Subject: [PATCH] fix(ui): raise design tokens to clear WCAG AA contrast MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses the preexisting contrast violations surfaced by the axe-core suite so the a11y spec now passes with no exceptions: - --primary-color: #007AFF → #0062CC. Clears AA 4.5:1 for white text on .btn-primary (was 4.01:1 → now 5.79:1) in both color schemes. Also used as text color on --primary-light tinted backgrounds; darker blue reads better there too. - --primary-light / --primary-lighter: RGB updated to match the new base. - --text-secondary opacity 0.6 → 0.76 (light mode). Fixes sidebar nav inactive items, .section-description, empty-state copy — all dropped below AA on white surfaces. - --text-secondary #8E8E93 → #AEAEB2 (dark mode). Fixes sidebar nav on the translucent near-black sidebar bg. - .nav-item.active in dark mode: override to --text-primary (white). --primary-color #0062CC is too saturated to stay readable on the --primary-light tint over the dark sidebar. Mirrored the changes in popup.css so both extension surfaces share tokens. Empties KNOWN_CONTRAST_EXCEPTIONS in e2e/a11y.spec.ts — the suite now runs with no allowlist, so any future regression fails immediately. --- e2e/a11y.spec.ts | 29 ++++------------------------- options.css | 17 +++++++++++++---- popup.css | 10 +++++----- 3 files changed, 22 insertions(+), 34 deletions(-) diff --git a/e2e/a11y.spec.ts b/e2e/a11y.spec.ts index bf92aec..3a94225 100644 --- a/e2e/a11y.spec.ts +++ b/e2e/a11y.spec.ts @@ -1,31 +1,10 @@ import AxeBuilder from '@axe-core/playwright' import { test, expect, type Page } from './fixture' -// Known preexisting violations — these are design decisions that need -// product/design sign-off to change (e.g. tweaking brand colors). The spec -// filters them out so this suite passes today and NEW regressions will still -// fail. When you accept a violation here, link an issue so it's tracked. -// -// .btn-primary: white text on #007AFF gives 4.01:1 (AA needs 4.5:1 for 13px -// normal). Fixing requires either darkening the brand blue or bumping button -// text to a size/weight that qualifies as "large text" (3:1 threshold). -// -// .nav-item (sidebar nav text "Proxy Profiles" / "About"), .section-description, -// empty-state paragraphs: all use --text-secondary for visual hierarchy, which -// at rgba(60,60,67,0.6) doesn't clear AA 4.5:1 on light backgrounds. Global -// fix: raise --text-secondary opacity to ~0.72 (or #595962), which would push -// everything above 4.5:1 in one token change. -const KNOWN_CONTRAST_EXCEPTIONS: Array = [ - /#addProfileBtn/, - /#saveAllBtn/, - /#saveProfileBtn/, - /#importProfilesBtn/, - /#exportProfilesBtn/, - /\.btn-primary/, - /li\[data-section=/, - /\.section-description/, - /\.empty-state/, -] +// Known preexisting violations — filtered here so the suite passes today while +// NEW regressions still fail. Keep this list minimal and annotated: each entry +// is a design decision the project has consciously accepted. Empty by default. +const KNOWN_CONTRAST_EXCEPTIONS: Array = [] function isKnownException(target: string[]): boolean { return target.some(sel => diff --git a/options.css b/options.css index 28d90db..0093f14 100644 --- a/options.css +++ b/options.css @@ -1,9 +1,9 @@ /* Global Styles - Apple Human Interface Guidelines Inspired */ :root { /* Color System */ - --primary-color: #007AFF; + --primary-color: #0062CC; --primary-hover: #0051D5; - --primary-light: rgba(0, 122, 255, 0.1); + --primary-light: rgba(0, 98, 204, 0.1); --secondary-color: #5856D6; --secondary-hover: #4240C4; --success-color: #34C759; @@ -16,7 +16,7 @@ /* Text Colors */ --text-primary: rgba(0, 0, 0, 0.85); - --text-secondary: rgba(60, 60, 67, 0.6); + --text-secondary: rgba(60, 60, 67, 0.76); --text-tertiary: rgba(60, 60, 67, 0.3); --text-inverse: #FFFFFF; @@ -134,7 +134,7 @@ @media (prefers-color-scheme: dark) { :root { --text-primary: #FFFFFF; - --text-secondary: #8E8E93; + --text-secondary: #AEAEB2; --text-tertiary: #48484A; --background: #000000; @@ -364,6 +364,15 @@ html { box-shadow: inset 0 1px 3px rgba(0, 122, 255, 0.1); } +/* Dark-mode override: --primary-color (#0062CC) isn't readable on the + near-black sidebar even with the --primary-light tint. iOS convention + (and WCAG AA) here is white text + tinted bg. */ +@media (prefers-color-scheme: dark) { + .nav-item.active { + color: var(--text-primary); + } +} + .nav-item.active .icon { animation: pulse 2s infinite; } diff --git a/popup.css b/popup.css index 2765742..85ac12e 100644 --- a/popup.css +++ b/popup.css @@ -9,10 +9,10 @@ :root { /* Color System - Apple Human Interface Guidelines */ - --primary-color: #007AFF; + --primary-color: #0062CC; --primary-hover: #0051D5; - --primary-light: rgba(0, 122, 255, 0.1); - --primary-lighter: rgba(0, 122, 255, 0.05); + --primary-light: rgba(0, 98, 204, 0.1); + --primary-lighter: rgba(0, 98, 204, 0.05); --secondary-color: #5856D6; --secondary-hover: #4240C4; --success-color: #34C759; @@ -25,7 +25,7 @@ /* Text Colors */ --text-primary: rgba(0, 0, 0, 0.85); - --text-secondary: rgba(60, 60, 67, 0.6); + --text-secondary: rgba(60, 60, 67, 0.76); --text-tertiary: rgba(60, 60, 67, 0.3); --text-inverse: #FFFFFF; @@ -88,7 +88,7 @@ --surface-bright: rgba(44, 44, 46, 0.9); --surface-brightest: rgba(44, 44, 46, 1); --text-primary: #FFFFFF; - --text-secondary: #8E8E93; + --text-secondary: #AEAEB2; --text-tertiary: #48484A; --border-color: #38383A; --border-hover: #48484A;