From 47a78896c531bad4d0c6413612cfbd0a79941b31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sat, 18 Jul 2026 10:26:05 +0200 Subject: [PATCH] fix(a11y): heading semantics for two metric sub-page sections The target-summary and coach-read strip tiles sit directly under a metric sub-page's h1, alongside the stat strip that already renders its title as an h2. Render their titles as real h2 headings too via the existing titleAs prop, so heading navigation lands on each section. A test pins that the dashboard exposes its page-level h1 through the shared page header (no duplicate sr-only heading needed). --- .../dashboard/__tests__/dashboard-header.test.tsx | 11 +++++++++++ src/components/insights/derived/coach-read-strip.tsx | 3 +++ src/components/insights/metric-target-summary.tsx | 3 +++ 3 files changed, 17 insertions(+) diff --git a/src/components/dashboard/__tests__/dashboard-header.test.tsx b/src/components/dashboard/__tests__/dashboard-header.test.tsx index 7746aaf6a..9b45f6014 100644 --- a/src/components/dashboard/__tests__/dashboard-header.test.tsx +++ b/src/components/dashboard/__tests__/dashboard-header.test.tsx @@ -43,4 +43,15 @@ describe(" — greeting", () => { // The title itself stays. expect(html).toContain("Dashboard"); }); + + // 2026-07-17 a11y audit (M4) — the dashboard is the app's landing surface + // and must expose a page-level `

`. It comes from the shared + // `PageHeader` the header renders, so a screen-reader user navigating by + // heading lands on a real page anchor (not the Today hero's muted `

` + // micro-label). No separate sr-only heading is added — that would double + // the `h1`. + it("renders a real page-level h1 with the dashboard title", () => { + const html = renderSSR( undefined} />); + expect(html).toMatch(/]*>Dashboard<\/h1>/); + }); }); diff --git a/src/components/insights/derived/coach-read-strip.tsx b/src/components/insights/derived/coach-read-strip.tsx index 8971fd4ea..94a847fee 100644 --- a/src/components/insights/derived/coach-read-strip.tsx +++ b/src/components/insights/derived/coach-read-strip.tsx @@ -123,6 +123,9 @@ export function CoachReadStrip({ diff --git a/src/components/insights/metric-target-summary.tsx b/src/components/insights/metric-target-summary.tsx index 41d4eec69..aec8c9079 100644 --- a/src/components/insights/metric-target-summary.tsx +++ b/src/components/insights/metric-target-summary.tsx @@ -316,6 +316,9 @@ function TargetReferencePanel({