Browse the docs

Pagination

Page numbers as small stickers. The current page is inked in; long runs leave a little ellipsis between the pages that matter. Uses the same paper edge, seeded tilt and press feedback as Button.

Server-compatibleWCAG AA

Page 1 of 20

Compact: Page 2 of 17

First and last: Page 12 of 40

Compact with ends: Page 9 of 17

Slow fetch: Page 3 of 12

Change every prop live in the playground.

Props

PropTypeDefaultWhat it does
pagerequirednumber—Current page, starting at 1. Values outside the range are clamped.
pageCountrequirednumber—Total number of pages. Zero renders no pagination.
asElementTypeaRouter link component, e.g. Next.js Link. Used with href.
disabledbooleanfalseDisable all navigation.
firstLabelstringFirstFirst control label, with showEnds.
formatCount(page: number, pageCount: number) => string(page, count) => ${page} of ${count}The compact variant's count.
getPageLabel(page: number) => stringn => Page ${n}Accessible name for each numbered page.
href(page: number) => stringnoneBuild a destination for each page to render links instead of buttons.
lastLabelstringLastLast control label, with showEnds.
loadingbooleanfalseThe current page is still fetching: it shows a spinner and the nav is `aria-busy`. Other pages stay usable.
loadingLabelstringLoadingScreen reader text while loading.
nextLabelstringNextNext control label.
onPageChange(page: number) => voidnoneCalled when a different page is activated. Required for button-mode navigation.
previousLabelstringPreviousPrevious control label.
seedstring | numberpaginationStable sticker tilts.
showEndsbooleanfalseAdd First and Last controls, for long lists where people jump to the ends.
variant"full" | "compact"full`full` shows page numbers. `compact` shows "2 of 17" between Previous and Next, for cards and toolbars.

Also takes every attribute of <nav> (278 more, e.g. onClick, className, aria-*).

Use it well

DoUse links for destinations that have a URL; use buttons for local lists. Keep page controlled by the same state that selects your results.
Don'tUse arrow-key widget navigation or focus a different page after every click. Tab, Enter and Space already work through native links and buttons.

Accessibility

  • A nav labelled Pagination contains native buttons or links. Override aria-label when you show more than one pagination landmark.
  • The selected page has aria-current=page and an ink fill. Numbered controls have names like Page 3; getPageLabel can translate them.
  • Previous and Next are disabled at the bounds. Disabled link destinations render as native disabled buttons without href.
  • Ellipses are decorative and have no tab stop. Large page counts render a bounded window rather than every page.
  • The compact variant reads its count as plain text in the nav; formatCount translates it. First and Last are disabled at the ends, like Previous and Next.
  • loading sets aria-busy on the nav. The current page becomes a busy button whose spinner says loadingLabel; other pages stay usable, so the latest pick wins.
  • Controls are at least 44px tall and wrap in narrow containers. Reused Button styles provide token contrast, focus, press feedback and reduced-motion handling.
Five stamps!

All aboard.

You took the whole tour. Here's Holo Pip, a foil sticker for riders who finish. It's in your playground tray now, for good.