Pagination
Links between the pages of a long list
Composablebuilt onButton
Pagination links the pages of a long list, like search results, tables, and feeds. A solid fill marks the current page and glides to the new one when it changes.
Preview
Installation
Usage
Composition
Mark the current page with isActive, and use isDisabled on Previous at the first page and Next at the last.
Examples
Page Range
Use getPaginationRange to get the pages and ellipses to show; it returns the same number of items for every page, so the row keeps its width.
Set siblingCount for pages beside the current one and boundaryCount for pages kept at each end. Both default to 1.
Router Links
Pass render to use your router's link, so changing pages doesn't reload the document.
Variants
Use variant on PaginationContent to pick the shell around the links.
| Variant | Description |
|---|---|
outline | The default. An outline Button's fill and border. |
soft | A secondary Button's fill, no edge. |
ghost | No shell. |
Size
Use size on PaginationContent to match a Button of the same size.
Set [--radius:9999px] for a pill. Recolor the current page with --pagination-current-bg and --pagination-current-fg.
Compact
Use PaginationStatus between Previous and Next to show the position alone.
Accessibility
Landmark and current page
Pagination is a nav labeled "Pagination", and the current page's link has aria-current="page". In forced-colors mode the current page gets a Highlight border, since the fill disappears.
Previous and Next
Below the sm breakpoint they show only their arrows. Their label stays as the accessible name, so a custom or translated label carries through.
Disabled links
A disabled link leaves the tab order, blocks its click, and drops its href. A router link passed through render keeps the href it requires, but its click is still blocked.
Status and motion
PaginationStatus is a polite live region, so screen readers announce the new position. With reduced motion, the current-page fill moves without sliding.
API Reference
Pagination is a custom component built from plain HTML elements; every prop below is specific to it. Each part also accepts the props of the element it renders (nav, ul, li, a, or span).
Utilities
getPaginationRange
Takes { page, pageCount, siblingCount?, boundaryCount? } and returns page numbers, "start-ellipsis", and "end-ellipsis". The page clamps to 1..pageCount. In a Server Component, import it from pagination/lib/range, since the pagination module is a client module.
Props
PaginationContent
The list and its shell. Renders a ul.
PaginationLink
A page link. Renders an a. PaginationPrevious and PaginationNext build on it and take the same props.
PaginationPrevious / PaginationNext
Links to the previous and next page, with an arrow.
Notes
PaginationEllipsis
Stands in for skipped pages. Renders a span that screen readers announce as "More pages".
PaginationStatus
A read-only position, like "Page 3 of 12". Renders an li that is a polite live region.
Upgrading
If you're reinstalling over an earlier version, check these changes:
| Before | Now |
|---|---|
Installed as cubby-ui/pagination.tsx | Installs into a cubby-ui/pagination/ folder with pagination.css and lib/range.ts. Import from @/components/ui/cubby-ui/pagination/pagination and delete the old file. |
| Bare links, the current page an outline button | A shell (outline by default) with a gliding fill. Use variant="ghost" for none. |
PaginationLink took a size | Set size once on PaginationContent. |
aria-label="pagination" on nav | aria-label="Pagination", overridable. |
| Previous and Next had fixed accessible names | Their label is the accessible name; it's visually hidden below sm. |