Pagination
Page links, with the current page marked and the ends always reachable.
Code
The three render the same class names, the same ARIA and the same data attributes. That is checked when this site builds: a class in any of these samples that neither the markup contract nor the shipped stylesheet defines fails the build.
<nav class="wsu-pagination" aria-label="Catalog pages">
<ul class="wsu-pagination__list">
<li><a class="wsu-pagination__link" href="?page=1" aria-disabled="true" aria-label="Previous page">
<svg class="wsu-icon" aria-hidden="true"><use href="/assets/wayne-ui/icons.svg#wsu-chevron-left"/></svg></a></li>
<li><a class="wsu-pagination__link" href="?page=1" aria-current="page">1</a></li>
<li><a class="wsu-pagination__link" href="?page=2">2</a></li>
<li><a class="wsu-pagination__link" href="?page=3">3</a></li>
<li><a class="wsu-pagination__link" href="?page=2" aria-label="Next page">
<svg class="wsu-icon" aria-hidden="true"><use href="/assets/wayne-ui/icons.svg#wsu-chevron-right"/></svg></a></li>
</ul>
</nav><x-wsu::pagination :paginator="$courses" label="Catalog pages" /><Pagination
:current="page"
:total="lastPage"
label="Catalog pages"
:href="(n) => `/catalog?page=${n}`"
/>Why it works this way
- Omit the href builder and the items render as buttons and the component emits change. An a without an href is not focusable and has no link role, so it is never the fallback.
- The elision is an aria-hidden span, so a screen reader hears the pages rather than an ellipsis character.
- Previous and Next stay in the list at both ends of the range, marked aria-disabled rather than removed. A control that vanishes the moment it is pressed leaves focus with nowhere to go but the body, and the next Tab lands past everything that followed it.
Accessibility
- nav with a name (1.3.1).
- aria-current="page" on the current page (4.1.2).
- Previous and Next carry aria-label because their content is an icon, and stay present with aria-disabled at either end rather than disappearing (2.4.3, 4.1.2).
Success criteria in brackets refer to WCAG 2.2. Every one of them is checked by axe-core in both themes at three viewport widths before this page can be published. See Accessibility for what the gates are.
Props
Blade
| Attribute | Default | What it does |
|---|---|---|
paginator | null | A Laravel paginator. |
links | null | Or a plain array of links. |
label | 'Pagination' | Names the nav. |
Vue
| Prop | Type and default | What it does |
|---|---|---|
current / total | Number, 1 / 1 | Page numbers. |
label | String, 'Pagination' | Names the nav landmark. |
href | Function, null | Builds each href. Omit it for a JavaScript pager. |
siblings | Number, 1 | Page links either side of the current page before the list elides. |
In the markup contract
contract/markup-contract.json is extracted from the two static templates and every package tests against it. This is what it records for .wsu-pagination.
| Template | Elements | Accessibility attributes | Uses |
|---|---|---|---|
| public apps/examples/static-html/public-app.html | nav | aria-label | 1 |