diff --git a/.changeset/lemon-pigs-mix.md b/.changeset/lemon-pigs-mix.md new file mode 100644 index 00000000000..616ae88d36e --- /dev/null +++ b/.changeset/lemon-pigs-mix.md @@ -0,0 +1,5 @@ +--- +'@primer/react': patch +--- + +Adds new a11y improvements to Pagination. diff --git a/src/Pagination/model.tsx b/src/Pagination/model.tsx index 1ba6f323b18..914ab52d24f 100644 --- a/src/Pagination/model.tsx +++ b/src/Pagination/model.tsx @@ -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, @@ -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 @@ -98,6 +104,7 @@ export function buildPaginationModel( type: 'NUM', num, selected, + precedesBreak: false, }) } } @@ -124,6 +131,7 @@ type PageType = { num: number disabled?: boolean selected?: boolean + precedesBreak?: boolean } export function buildComponentData( @@ -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': { diff --git a/src/__tests__/Pagination/PaginationModel.test.tsx b/src/__tests__/Pagination/PaginationModel.test.tsx index a119873f346..3a3ba2e6273 100644 --- a/src/__tests__/Pagination/PaginationModel.test.tsx +++ b/src/__tests__/Pagination/PaginationModel.test.tsx @@ -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}, @@ -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}, @@ -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) @@ -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'}, ] diff --git a/src/__tests__/Pagination/__snapshots__/Pagination.test.tsx.snap b/src/__tests__/Pagination/__snapshots__/Pagination.test.tsx.snap index 7197e07d306..889609579e2 100644 --- a/src/__tests__/Pagination/__snapshots__/Pagination.test.tsx.snap +++ b/src/__tests__/Pagination/__snapshots__/Pagination.test.tsx.snap @@ -129,12 +129,15 @@ exports[`Pagination renders consistently 1`] = ` > Previous - 1 - +