Skip to content

More a11y improvements for Pagination #3029

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lemon-pigs-mix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': patch
---

Adds new a11y improvements to Pagination.
28 changes: 20 additions & 8 deletions src/Pagination/model.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ export function buildPaginationModel(
for (let idx = 0; idx < sorted.length; idx++) {
const num = sorted[idx]
const selected = num === currentPage
const last = sorted[idx - 1]
const next = sorted[idx + 1]
const lastDelta = num - last
const nextDelta = num - next
const precedesBreak = nextDelta !== -1

if (idx === 0) {
if (num !== 1) {
// If the first page isn't page one,
Expand All @@ -78,15 +84,15 @@ export function buildPaginationModel(
type: 'NUM',
num,
selected,
precedesBreak,
})
} else {
const last = sorted[idx - 1]
const delta = num - last
if (delta === 1) {
if (lastDelta === 1) {
pages.push({
type: 'NUM',
num,
selected,
precedesBreak,
})
} else {
// We skipped some, so add a break
Expand All @@ -98,6 +104,7 @@ export function buildPaginationModel(
type: 'NUM',
num,
selected,
precedesBreak: false,
})
}
}
Expand All @@ -124,6 +131,7 @@ type PageType = {
num: number
disabled?: boolean
selected?: boolean
precedesBreak?: boolean
}

export function buildComponentData(
Expand Down Expand Up @@ -169,11 +177,15 @@ export function buildComponentData(
case 'NUM': {
key = `page-${page.num}`
content = String(page.num)
if (page.selected) {
Object.assign(props, {as: 'em', 'aria-current': 'page'})
} else {
Object.assign(props, {href: hrefBuilder(page.num), 'aria-label': `Page ${page.num}`, onClick})
}
Object.assign(props, {
href: hrefBuilder(page.num),
// We append "..." to the aria-label for pages that preceed a break because screen readers will
// change the tone the text is read in.
// This is a slightly nicer experience than skipping a bunch of numbers unexpectedly.
'aria-label': `Page ${page.num}${page.precedesBreak ? '...' : ''}`,
onClick,
'aria-current': page.selected ? 'page' : undefined,
})
break
}
case 'BREAK': {
Expand Down
10 changes: 5 additions & 5 deletions src/__tests__/Pagination/PaginationModel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ describe('Pagination model', () => {
const slice = last(model, 5)

const expected = [
{type: 'NUM'},
{type: 'NUM', precedesBreak: true},
{type: 'BREAK'},
{type: 'NUM', num: 9},
{type: 'NUM', num: 10},
Expand All @@ -74,11 +74,11 @@ describe('Pagination model', () => {
const model = buildPaginationModel(10, 5, true, 1, 1)
const expected = [
{type: 'PREV', num: 4},
{type: 'NUM', num: 1},
{type: 'NUM', num: 1, precedesBreak: true},
{type: 'BREAK'},
{type: 'NUM', num: 4},
{type: 'NUM', num: 5, selected: true},
{type: 'NUM', num: 6},
{type: 'NUM', num: 6, precedesBreak: true},
{type: 'BREAK'},
{type: 'NUM', num: 10},
{type: 'NEXT', num: 6},
Expand All @@ -95,7 +95,7 @@ describe('Pagination model', () => {
{type: 'NUM', num: 3},
// normally with a surround of 1, only 1 and 3 would be shown
// however, since 1 was already shown, we extend to 4
{type: 'NUM', num: 4},
{type: 'NUM', num: 4, precedesBreak: true},
{type: 'BREAK'},
]
expect(first(model, 6)).toMatchObject(expected)
Expand Down Expand Up @@ -123,7 +123,7 @@ describe('Pagination model', () => {
{type: 'BREAK', num: 1},
{type: 'NUM', num: 4},
{type: 'NUM', num: 5, selected: true},
{type: 'NUM', num: 6},
{type: 'NUM', num: 6, precedesBreak: true},
{type: 'BREAK', num: 10},
{type: 'NEXT'},
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,15 @@ exports[`Pagination renders consistently 1`] = `
>
Previous
</span>
<em
<a
aria-current="page"
aria-label="Page 1"
className="c2"
href="#1"
onClick={[Function]}
>
1
</em>
</a>
<a
aria-label="Page 2"
className="c2"
Expand Down Expand Up @@ -168,7 +171,7 @@ exports[`Pagination renders consistently 1`] = `
5
</a>
<a
aria-label="Page 6"
aria-label="Page 6..."
className="c2"
href="#6"
onClick={[Function]}
Expand Down