Pagination
Navigation between pages of results. Pagination keeps no state: pages can be URLs (plain anchors or your router's links) or buttons driven by your own state.
Installation
Add Pagination to your project with the CK-UI CLI. It copies the source into your project, so the code is yours to change.
- Adds
Pagination.tsxto your CK-UI folder (src/components/ck-ui by default)- Installs
@radix-ui/react-slotreact-iconsif your project does not have them yet
First time with CK-UI in this project? Run npx ck-ui-cli@latest init once before adding components. The installation guide explains what it sets up.
Manual installationInstall the packages and copy the files yourself.
Install the following dependencies
Run these commands in your terminal to install the required packages
Create or update your Pagination component
Copy this code to create your Pagination component
Test Your Component
- 1. Add the component to a test page
- 2. Check all props and variants work as expected
- 3. Verify responsive behavior
- 4. Test with different content/data
- 5. Ensure accessibility features work correctly
Many Pages
getPaginationRange({ page, pageCount }) returns the pages to show with "ellipsis" markers: first and last pages, the current page and one page either side.
Links
Give each page an href for a plain anchor, or wrap your router's link with asChild. This demo keeps page 2 current.
Previous / Next
Only previous and next, with the position as text in a polite status.
Compact
Small size and siblingCount 0 for narrow screens. Previous and Next show icons only below the sm breakpoint and keep their accessible names.
Accessibility
- A
<nav aria-label="Pagination">landmark around a list. Rename it when a page has more than one (aria-label="Blog pages"). - The current page has
aria-current="page". Numbered links are named "Page 3" rather than "3"; Previous and Next are "Go to previous page" and "Go to next page". - Disabled links lose their href (or become disabled buttons), so they leave the tab order and are announced as unavailable. With asChild, a disabled step replaces your link with an inert anchor that has the same content.
- Every page link is a real link or button with the shared focus ring. The ellipsis is announced as "More pages".
- When pages change without a navigation (client state), move focus to the results or announce the new page, as in the Previous / Next example.
API Reference
Server-compatible: render it and call getPaginationRange() from Server Components. Import with import * as Pagination from "@/components/ui/Pagination".
Pagination.Root
The nav landmark.
| Prop | Type | Default | Description |
|---|---|---|---|
aria-label | "string" | "Pagination" | Landmark name. |
className | "string" | "undefined" | Additional classes, merged last. |
Pagination.Content
The list.
| Prop | Type | Default | Description |
|---|---|---|---|
className | "string" | "undefined" | Additional classes, merged last. |
Pagination.Item
A list item.
| Prop | Type | Default | Description |
|---|---|---|---|
className | "string" | "undefined" | Additional classes, merged last. |
Pagination.Link
A page. An <a> with href, your element with asChild, otherwise a <button>.
| Prop | Type | Default | Description |
|---|---|---|---|
href | "string" | "undefined" | Renders an anchor. |
isActive | "boolean" | "false" | The current page: aria-current="page". |
disabled | "boolean" | "false" | Not interactive and out of the tab order. |
size | "sm""md" | "md" | 32 or 36px tall. |
aria-label | "string" | "Page {children}" | Accessible name; defaults to “Page N” for numeric text. |
onClick | "(event) => void" | "undefined" | For state you manage yourself. |
asChild | "boolean" | "false" | Render your router's link (e.g. Next.js Link). |
className | "string" | "undefined" | Additional classes, merged last. |
Pagination.Previous / Pagination.Next
Pagination.Link with an arrow and a visible label from the sm breakpoint.
| Prop | Type | Default | Description |
|---|---|---|---|
label | "string" | "Previous / Next" | Visible text. |
aria-label | "string" | "Go to previous / next page" | Accessible name. |
href | disabled | size | asChild | onClick | "-" | "-" | As on Pagination.Link. |
Pagination.Ellipsis
Marks skipped pages.
| Prop | Type | Default | Description |
|---|---|---|---|
label | "string" | "More pages" | Screen-reader text. |
size | "sm""md" | "md" | Matches the link size. |
className | "string" | "undefined" | Additional classes, merged last. |
getPaginationRange(options)
Returns (number | "ellipsis")[]. A gap of a single page shows that page instead of an ellipsis.
| Prop | Type | Default | Description |
|---|---|---|---|
page | "number" | "-" | Current page, 1-based (clamped). |
pageCount | "number" | "-" | Total pages. |
siblingCount | "number" | "1" | Pages on each side of the current page. |
boundaryCount | "number" | "1" | Pages always shown at the start and end. |