From 6fd360a381da94c9f8505282de59f5bae61c7102 Mon Sep 17 00:00:00 2001 From: Marcel Date: Fri, 8 May 2026 12:46:45 +0200 Subject: [PATCH] fix(a11y): focus-visible ring on reader-dashboard view-all links MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both view-all links (Alle Personen → in ReaderPersonChips, Alle Geschichten → in ReaderRecentStories) were missing the focus-visible:ring-2 ring used by every other interactive element on the reader dashboard, leaving keyboard users with no visible focus indicator. WCAG 2.1 §2.4.7 (Focus Visible, Level AA). Co-Authored-By: Claude Opus 4.7 --- .../src/lib/shared/dashboard/ReaderPersonChips.svelte | 2 +- .../lib/shared/dashboard/ReaderPersonChips.svelte.spec.ts | 8 ++++++++ .../src/lib/shared/dashboard/ReaderRecentStories.svelte | 2 +- .../shared/dashboard/ReaderRecentStories.svelte.spec.ts | 8 ++++++++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/frontend/src/lib/shared/dashboard/ReaderPersonChips.svelte b/frontend/src/lib/shared/dashboard/ReaderPersonChips.svelte index 57a602df..960162d2 100644 --- a/frontend/src/lib/shared/dashboard/ReaderPersonChips.svelte +++ b/frontend/src/lib/shared/dashboard/ReaderPersonChips.svelte @@ -54,7 +54,7 @@ const { persons }: Props = $props(); {m.dashboard_reader_all_persons()} diff --git a/frontend/src/lib/shared/dashboard/ReaderPersonChips.svelte.spec.ts b/frontend/src/lib/shared/dashboard/ReaderPersonChips.svelte.spec.ts index a24da959..c0491597 100644 --- a/frontend/src/lib/shared/dashboard/ReaderPersonChips.svelte.spec.ts +++ b/frontend/src/lib/shared/dashboard/ReaderPersonChips.svelte.spec.ts @@ -58,6 +58,14 @@ describe('ReaderPersonChips', () => { await expect.element(allLink).toHaveAttribute('href', '/persons'); }); + it('exposes a focus-visible ring on the "Alle Personen" link', async () => { + render(ReaderPersonChips, { persons: [person1] }); + const allLink = page.getByRole('link', { name: /Alle Personen/i }); + const cls = ((await allLink.element()) as HTMLElement).className; + expect(cls).toMatch(/focus-visible:ring-2/); + expect(cls).toMatch(/focus-visible:ring-brand-navy/); + }); + it('renders empty state without chips when persons array is empty', async () => { render(ReaderPersonChips, { persons: [] }); const chips = page.getByRole('link', { name: /Müller|Schmidt/ }); diff --git a/frontend/src/lib/shared/dashboard/ReaderRecentStories.svelte b/frontend/src/lib/shared/dashboard/ReaderRecentStories.svelte index fb27a398..0dc0579d 100644 --- a/frontend/src/lib/shared/dashboard/ReaderRecentStories.svelte +++ b/frontend/src/lib/shared/dashboard/ReaderRecentStories.svelte @@ -48,7 +48,7 @@ function excerpt(body: string | undefined): string { {m.dashboard_reader_all_stories()} diff --git a/frontend/src/lib/shared/dashboard/ReaderRecentStories.svelte.spec.ts b/frontend/src/lib/shared/dashboard/ReaderRecentStories.svelte.spec.ts index df7f3891..13102075 100644 --- a/frontend/src/lib/shared/dashboard/ReaderRecentStories.svelte.spec.ts +++ b/frontend/src/lib/shared/dashboard/ReaderRecentStories.svelte.spec.ts @@ -57,4 +57,12 @@ describe('ReaderRecentStories', () => { const allLink = page.getByRole('link', { name: /Alle Geschichten/i }); await expect.element(allLink).toHaveAttribute('href', '/geschichten'); }); + + it('exposes a focus-visible ring on the "Alle Geschichten" link', async () => { + render(ReaderRecentStories, { stories: [story1] }); + const allLink = page.getByRole('link', { name: /Alle Geschichten/i }); + const cls = ((await allLink.element()) as HTMLElement).className; + expect(cls).toMatch(/focus-visible:ring-2/); + expect(cls).toMatch(/focus-visible:ring-brand-navy/); + }); });