From 18b88672ec4d15145c631cee52a096b3a8739e07 Mon Sep 17 00:00:00 2001 From: Marcel Date: Fri, 24 Apr 2026 10:52:13 +0200 Subject: [PATCH] =?UTF-8?q?fix(pagination):=20bound=20controls=20render=20?= =?UTF-8?q?as=20aria-hidden=20spans=20=E2=80=94=20address=20@leonievoss?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit is the documented pattern but screen readers still announce "Previous, link, disabled" on pagination bounds — noise users don't need because the disabled state is purely visual. Switching to - - {m.pagination_prev()} - + + {#if hasPrev} + + + {m.pagination_prev()} + + {:else} + + {/if} - - {m.pagination_next()} - - + {#if hasNext} + + {m.pagination_next()} + + + {:else} + + {/if} {/if} diff --git a/frontend/src/lib/components/Pagination.svelte.spec.ts b/frontend/src/lib/components/Pagination.svelte.spec.ts index 68af1558..90bf8532 100644 --- a/frontend/src/lib/components/Pagination.svelte.spec.ts +++ b/frontend/src/lib/components/Pagination.svelte.spec.ts @@ -33,12 +33,14 @@ describe('Pagination', () => { await expect.element(prev).toHaveAttribute('href', '/documents?page=3'); }); - it('disables prev on page 0 (no href, aria-disabled="true")', async () => { + it('renders disabled prev as an aria-hidden non-link so screen readers skip it', async () => { render(Pagination, { page: 0, totalPages: 3, makeHref }); const prev = page.getByTestId('pagination-prev'); - await expect.element(prev).toHaveAttribute('aria-disabled', 'true'); + // Not a link — no href, no role=link await expect.element(prev).not.toHaveAttribute('href'); + // Hidden from assistive tech — AT shouldn't read "Previous, link, disabled" + await expect.element(prev).toHaveAttribute('aria-hidden', 'true'); }); it('renders next as a link pointing at page + 1 when not on last page', async () => { @@ -48,12 +50,12 @@ describe('Pagination', () => { await expect.element(next).toHaveAttribute('href', '/documents?page=1'); }); - it('disables next on the last page (no href, aria-disabled="true")', async () => { + it('renders disabled next as an aria-hidden non-link on the last page', async () => { render(Pagination, { page: 2, totalPages: 3, makeHref }); const next = page.getByTestId('pagination-next'); - await expect.element(next).toHaveAttribute('aria-disabled', 'true'); await expect.element(next).not.toHaveAttribute('href'); + await expect.element(next).toHaveAttribute('aria-hidden', 'true'); }); it('calls makeHref with p-1 and p+1', async () => {