Pagination
The pages of a long list, and how many rows a page holds, said in one sentence that can be edited where it stands.
Try it
Press the number in the sentence and type another, or open its list. Go to the last page: the sentence says how many rows are in view, which is not the page size.
The page size, in the sentence
The drawing sets a Select beside the words: “Show”, a field 40 tall holding 10, then “1-10 of 72 results”. A footer is a quiet place and that is its loudest part, for something changed once a session. So the number moved into the sentence. It shows at rest that it can be changed, by its weight and its chevron and not only under the pointer, because a touch screen has no hover to find it with.
A number that can be typed or picked is an editable combobox whose list suggests and does not filter, so 17 is as good a page size as 25. It is not the browser’s datalist, whose list takes no styling, does not follow page zoom, and is not announced by every screen reader; and it is not a number input, which brings spinners, a wheel that changes the value, and “e” accepted as a digit.
| Key | Does |
|---|---|
| Digits | Type any page size. Nothing else is accepted. |
| Enter, or leaving the field | Takes the number. Zero or nothing puts the old one back. |
| Down, Up | Open the list at the size in use, and move through it. |
| Alt + Down | Opens the list and chooses nothing. |
| Esc | Closes the list. Again, puts back what was typed over. |
“Showing 10 of 72 results” is false on the last page, where two are showing. So the field is the page size and the range beside it says what is in view. Changing the size keeps the reader’s place: the new page is the one that holds the first row they were looking at.
A sentence in another language
Word order belongs to a language, so the sentence is the caller’s: summary is handed the field and the numbers and returns the words around them. The field’s own name, the arrows’ and each page’s are props too.
Seven places
With more pages than fit there are seven places, always: the first and last page, the current one with a neighbour each side, and an ellipsis where pages are skipped. The arrows never move, so Next can be pressed again without looking for it. An ellipsis never stands for a single page, which would save nothing and cost a press.
| Page | Shown |
|---|---|
| 1 of 3 | 1 2 3 |
| 1 of 24 | 1 2 3 4 5 … 24 |
| 8 of 24 | 1 … 7 8 9 … 24 |
| 24 of 24 | 1 … 20 21 22 23 24 |
Anatomy
| Part | Value |
|---|---|
| Page and arrow | 40 square, round |
| Text, Medium | 14 / 22 |
| Bar under the current page | 2 by 16 |
| Caret | 16 |
| Page size field | 32 tall, radius 8 |
| Its list | rows of 32, radius 12 |
The current page is the drawn bar in the accent, and its number is primary where the others are secondary: a bar two pixels tall is a thin difference on its own. The published item draws every number in primary; the drawn footer already has the others in grey.
Accessibility
A nav with a name, holding a list of buttons: the current one carries aria-current="page" and each is named “Page 3”, not “3”. The ellipsis is text. After a press the page arrived at is said, politely. At either end an arrow is aria-disabled and not disabled: pressing Next onto the last page would otherwise disable the button under the focus and drop the focus to the top of the page. With hrefFor the pages are links, for paging that lives in the URL. The carets turn over under dir="rtl".
Props
| Prop | Type | Default |
|---|---|---|
page | number | required |
onPageChange | (page: number) => void | required |
pageCount | number | from total and pageSize |
total | number | — |
pageSize | number | — |
onPageSizeChange | (size: number) => void | — |
pageSizeOptions | readonly number[] | [10, 25, 50, 100] |
maxPageSize | number | 100 |
summary | ({ size, from, to, total }) => React | the English sentence |
hrefFor | (page: number) => string | — |
renderLink | (props: Link | — |
siblings, boundaries | number | 1, 1 |
label | string | 'Pagination' |
previousLabel, nextLabel | string | 'Previous page', 'Next page' |
pageSizeLabel | string | 'Results per page' |
pageLabel | (page: number) => string | `Page ${page}` |
announce | boolean | true |
className | string | — |