Navigation
Pagination
A navigation landmark that exposes the current page and page controls.
When to use it: Use it to move between discrete pages of results, not to load more content in place.
Example
import {
Pagination,
PaginationEllipsis,
PaginationFirst,
PaginationItem,
PaginationLast,
PaginationList,
PaginationNext,
PaginationPage,
PaginationPrevious,
} from "@comp0/react";
export function Example() {
return (
<Pagination defaultPage={6} totalPages={20}>
{({ pages }) => (
<PaginationList className="flex items-center gap-1">
<PaginationItem>
<PaginationFirst className="rounded px-2.5 py-2 text-sm hover:bg-zinc-100 disabled:opacity-40 dark:hover:bg-zinc-800">
First
</PaginationFirst>
</PaginationItem>
<PaginationItem>
<PaginationPrevious className="rounded px-2.5 py-2 text-sm hover:bg-zinc-100 disabled:opacity-40 dark:hover:bg-zinc-800">
Previous
</PaginationPrevious>
</PaginationItem>
{pages.map((entry) => (
<PaginationItem key={entry}>
{typeof entry === "number" ? (
<PaginationPage
page={entry}
className="size-9 rounded text-sm hover:bg-zinc-100 data-current:bg-zinc-900 data-current:text-white dark:hover:bg-zinc-800 dark:data-current:bg-zinc-100 dark:data-current:text-zinc-950"
>
{entry}
</PaginationPage>
) : (
<PaginationEllipsis className="grid size-9 place-items-center text-zinc-500" />
)}
</PaginationItem>
))}
<PaginationItem>
<PaginationNext className="rounded px-2.5 py-2 text-sm hover:bg-zinc-100 disabled:opacity-40 dark:hover:bg-zinc-800">
Next
</PaginationNext>
</PaginationItem>
<PaginationItem>
<PaginationLast className="rounded px-2.5 py-2 text-sm hover:bg-zinc-100 disabled:opacity-40 dark:hover:bg-zinc-800">
Last
</PaginationLast>
</PaginationItem>
</PaginationList>
)}
</Pagination>
);
}Anatomy
Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.
A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.
Pagination
Native navigation landmark that owns the current page and visible page range. Owns a DOM element.
PaginationList
Native ul for the controls. Owns a DOM element.
PaginationItem
Native li wrapping one control or ellipsis. Owns a DOM element.
PaginationPage
Button or link that selects a numbered page. Owns a DOM element.
PaginationPrevious / PaginationNextOptional
Move one page and disable at their bounds. Owns a DOM element.
PaginationFirst / PaginationLastOptional
Move to the first or last page and disable at their bounds. Owns a DOM element.
PaginationEllipsisOptional
Presentational omission marker hidden from assistive technology. Owns a DOM element.
Step by step
- 1
Add the main part
Start Pagination with totalPages and render its pages state in a PaginationList.
- 2
Add the supporting parts
Wrap every control or generated page in PaginationItem; render ellipsis entries with PaginationEllipsis.
- 3
Make the behavior clear
Use page and onChange for controlled navigation, or defaultPage for an initial page; previous and next controls disable at their bounds.
Exampletsx <Pagination totalPages={20}> {({ pages }) => ( <PaginationList> {pages.map((page) => ( <PaginationItem key={page}> {typeof page === "number" ? ( <PaginationPage page={page}>{page}</PaginationPage> ) : ( <PaginationEllipsis /> )} </PaginationItem> ))} </PaginationList> )} </Pagination>;
Keyboard
- ⇥
- Moves through the available page controls.
- ↵
- Selects the focused page or direction.
- Space
- Selects the focused page or direction.
Forms and accessibility
Pagination changes application navigation state and does not create form values.
Accessibility checklist
- Use a navigation label that distinguishes this pagination from other page navigation.
- PaginationPage marks the current page with aria-current=page; do not duplicate that state manually.
- Ellipses are hidden from assistive technology, so expose only real reachable page controls.
API reference
import { Pagination, PaginationEllipsis, PaginationFirst, PaginationItem, PaginationLast, PaginationList, PaginationNext, PaginationPage, PaginationPrevious } from "@comp0/react";Pagination
DOM elementNative navigation landmark that owns the current page and visible page range.
| Prop | Type | Description |
|---|---|---|
page | number | Controlled one-based page. |
defaultPage | number | Initial one-based page. |
onChange | (page: number) => void | Receives the next clamped page. |
totalPages | number | Required positive number of pages. |
siblingCount | number | How many neighboring and edge pages stay visible. |
boundaryCount | number | How many neighboring and edge pages stay visible. |
aria-label | string | Navigation name; defaults to "Pagination". |
PaginationList
DOM elementNative ul for the controls.
PaginationItem
DOM elementNative li wrapping one control or ellipsis.
PaginationPage
DOM elementButton or link that selects a numbered page.
| Prop | Type | Description |
|---|---|---|
page | number | The one-based page to select. |
as | ElementType | Renders a router-style link while keeping pagination behavior. |
PaginationPrevious / PaginationNext
OptionalDOM elementMove one page and disable at their bounds.
PaginationFirst / PaginationLast
OptionalDOM elementMove to the first or last page and disable at their bounds.
PaginationEllipsis
OptionalDOM elementPresentational omission marker hidden from assistive technology.
Style hooks
Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.
Pagination
| Style hook | Meaning |
|---|---|
[data-page] | The current one-based page. |
[data-first] | The current page is at a boundary. |
[data-last] | The current page is at a boundary. |
PaginationPage
| Style hook | Meaning |
|---|---|
[data-current] | This page is current. |
PaginationPrevious / PaginationNext
| Style hook | Meaning |
|---|---|
:disabled | That direction is unavailable. |
PaginationFirst / PaginationLast
| Style hook | Meaning |
|---|---|
:disabled | That direction is unavailable. |