Skip to content
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