From 53af1807b62b4e408958ba60c5caae8f5f10f32e Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Thu, 18 Jun 2026 10:00:20 +0000 Subject: [PATCH] =?UTF-8?q?feat(ui):=20un-overload=20accent=20=E2=80=94=20?= =?UTF-8?q?nav=20rail,=20stronger=20focus=20ring,=20neutral=20hover?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Assisted-by: Claude:claude-opus-4-8 [Claude Code] Signed-off-by: Ettore Di Giacinto --- core/http/react-ui/e2e/design-system.spec.js | 9 +++++++++ core/http/react-ui/src/App.css | 16 ++++++++++++---- core/http/react-ui/src/theme.css | 8 ++++++-- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/core/http/react-ui/e2e/design-system.spec.js b/core/http/react-ui/e2e/design-system.spec.js index 8388d4553..fa9c4e009 100644 --- a/core/http/react-ui/e2e/design-system.spec.js +++ b/core/http/react-ui/e2e/design-system.spec.js @@ -8,4 +8,13 @@ test.describe('Editorial design system', () => { const family = await title.evaluate(el => getComputedStyle(el).fontFamily) expect(family.toLowerCase()).toContain('fraunces') }) + + test('active nav item shows a left accent rail (box-shadow), not just a tint', async ({ page }) => { + await page.goto('/app/settings') + await expect(page.locator('.page-title').first()).toBeVisible({ timeout: 15_000 }) + const active = page.locator('.sidebar-nav .nav-item.active').first() + await expect(active).toBeVisible() + const shadow = await active.evaluate(el => getComputedStyle(el).boxShadow) + expect(shadow).not.toBe('none') + }) }) diff --git a/core/http/react-ui/src/App.css b/core/http/react-ui/src/App.css index b0ce673b4..b450b8403 100644 --- a/core/http/react-ui/src/App.css +++ b/core/http/react-ui/src/App.css @@ -352,9 +352,10 @@ border-radius: var(--radius-lg); } .sidebar-nav .nav-item.active { - background: var(--color-primary-light); - color: var(--color-primary); - box-shadow: none; + background: var(--color-surface-hover); + color: var(--color-text-primary); + font-weight: var(--font-weight-medium); + box-shadow: inset 3px 0 0 var(--color-nav-rail); } .sidebar-nav .nav-item.active .nav-icon { color: var(--color-primary); } /* Align tier labels with the inset item text (item margin + icon padding). */ @@ -1624,6 +1625,13 @@ border-radius: var(--radius-sm); } +/* Solid outline fallback so the focus ring stays AA-visible (>=3:1) on every + interactive element, including those that clip or override box-shadow. */ +:focus-visible { + outline: 2px solid var(--color-focus-ring); + outline-offset: 2px; +} + .btn-primary { background: var(--color-primary); color: var(--color-primary-text); @@ -2390,7 +2398,7 @@ select.input { } .table tr:hover td { - background: var(--color-primary-light); + background: var(--color-surface-hover); } /* Toggle switch */ diff --git a/core/http/react-ui/src/theme.css b/core/http/react-ui/src/theme.css index b40cc413a..00fcd2977 100644 --- a/core/http/react-ui/src/theme.css +++ b/core/http/react-ui/src/theme.css @@ -64,7 +64,9 @@ --color-modal-backdrop: rgba(8, 11, 17, 0.68); - --color-focus-ring: rgba(136, 192, 208, 0.34); + --color-focus-ring: rgba(136, 192, 208, 0.7); /* was 0.34 - AA-visible */ + --color-nav-rail: var(--color-primary); + --color-eyebrow: #d8b48c; /* muted Nord-aurora brass for editorial eyebrows */ /* Data viz — full aurora + frost palette */ --color-data-1: #88c0d0; /* frost cyan */ @@ -219,7 +221,9 @@ --color-modal-backdrop: rgba(46, 52, 64, 0.38); - --color-focus-ring: rgba(94, 129, 172, 0.34); + --color-focus-ring: rgba(94, 129, 172, 0.6); /* was 0.34 */ + --color-nav-rail: var(--color-primary); + --color-eyebrow: #9a6b3f; /* darker brass for contrast on snow storm */ /* Data viz — muted aurora for light mode */ --color-data-1: #5e81ac;