fix(pagination): add sr-only span to preserve aria-current on mobile AT
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 3m2s
CI / OCR Service Tests (pull_request) Successful in 31s
CI / Backend Unit Tests (pull_request) Failing after 3m6s
CI / Unit & Component Tests (push) Failing after 2m58s
CI / OCR Service Tests (push) Successful in 35s
CI / Backend Unit Tests (push) Failing after 3m3s
Some checks failed
CI / Unit & Component Tests (pull_request) Failing after 3m2s
CI / OCR Service Tests (pull_request) Successful in 31s
CI / Backend Unit Tests (pull_request) Failing after 3m6s
CI / Unit & Component Tests (push) Failing after 2m58s
CI / OCR Service Tests (push) Successful in 35s
CI / Backend Unit Tests (push) Failing after 3m3s
When the mobile label is aria-hidden and the desktop button container is display:none (below sm:), mobile screen reader users had no aria-current indicator. Added a sr-only span with aria-current="page" that stays in the AT tree at all breakpoints regardless of CSS display state. On desktop the active page button also carries aria-current — both announce the same page information, which is acceptable. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -95,7 +95,7 @@ const pageWindow = $derived.by(() => {
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<!-- Mobile: "Seite X von Y" label (hidden on sm: and above) -->
|
<!-- Mobile: "Seite X von Y" label (hidden on sm: and above) -->
|
||||||
<!-- aria-hidden: desktop numbered buttons carry the aria-current="page" role; this label is redundant on wide screens -->
|
<!-- aria-hidden: decorative visual label; AT uses the sr-only span below for aria-current -->
|
||||||
<span
|
<span
|
||||||
data-testid="pagination-page-label"
|
data-testid="pagination-page-label"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
@@ -103,6 +103,12 @@ const pageWindow = $derived.by(() => {
|
|||||||
>
|
>
|
||||||
{m.pagination_page_of({ page: page + 1, total: totalPages })}
|
{m.pagination_page_of({ page: page + 1, total: totalPages })}
|
||||||
</span>
|
</span>
|
||||||
|
<!-- Always in the AT tree: announces current page regardless of breakpoint.
|
||||||
|
On mobile, the desktop button container is display:none so this is the only AT anchor.
|
||||||
|
On desktop, the active page button also carries aria-current — both announce the same info. -->
|
||||||
|
<span data-testid="pagination-current-page-sr" aria-current="page" class="sr-only">
|
||||||
|
{m.pagination_page_of({ page: page + 1, total: totalPages })}
|
||||||
|
</span>
|
||||||
|
|
||||||
<!-- Desktop: numbered page buttons (hidden below sm:) -->
|
<!-- Desktop: numbered page buttons (hidden below sm:) -->
|
||||||
<div data-testid="pagination-pages" class="hidden items-center gap-1 sm:flex">
|
<div data-testid="pagination-pages" class="hidden items-center gap-1 sm:flex">
|
||||||
|
|||||||
@@ -151,6 +151,15 @@ describe('Pagination', () => {
|
|||||||
await expect.element(label).toHaveAttribute('aria-hidden', 'true');
|
await expect.element(label).toHaveAttribute('aria-hidden', 'true');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sr-only span always provides aria-current="page" for screen readers at all breakpoints', async () => {
|
||||||
|
render(Pagination, { page: 2, totalPages: 10, makeHref });
|
||||||
|
|
||||||
|
const nav = page.getByRole('navigation');
|
||||||
|
const srLabel = nav.getByTestId('pagination-current-page-sr');
|
||||||
|
await expect.element(srLabel).toBeInTheDocument();
|
||||||
|
await expect.element(srLabel).toHaveAttribute('aria-current', 'page');
|
||||||
|
});
|
||||||
|
|
||||||
it('renders prev as a link pointing at page - 1 when not on first page', async () => {
|
it('renders prev as a link pointing at page - 1 when not on first page', async () => {
|
||||||
render(Pagination, { page: 4, totalPages: 10, makeHref });
|
render(Pagination, { page: 4, totalPages: 10, makeHref });
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user