Skip to Content
Puzzle
UI ComponentsNavigation

Pagination

Navigate between pages of a larger collection.

Pagination provides page-number and previous/next controls for content split across multiple pages. It supports both button-based state updates and URL-based links.

Import

import { Pagination } from "@puzzle-ui/ui";

Basic usage

Set totalPages to the number of pages and use defaultPage to choose the initial page for an uncontrolled pagination control. Page numbers start at 1.

390 × 160

Controlled page

Use page and onPageChange when the parent manages the selected page. The callback receives the new page number. Updating a controlled pagination requires updating page in response to that callback.

const [page, setPage] = useState(1);

<Pagination totalPages={10} page={page} onPageChange={setPage} />;

Without page, defaultPage sets the initial page and the component updates its own page state. The selected page is clamped to the available range; when totalPages is zero, page numbers are omitted and navigation controls are disabled.

Provide getPageHref to render available pages as links, for example when each page has a URL. The callback receives a page number and should return its destination. Current and disabled controls are not links.

390 × 160

Visible pages and controls

boundaryCount sets how many page numbers to keep visible at each end, and siblingCount sets how many page numbers appear beside the current page. Gaps of one page are shown as a page number; larger gaps use an ellipsis. When the total is small enough to fit the window, all pages are shown.

Set showFirstLast={false} to hide the first- and last-page controls. Use disabled to disable all navigation, and size="sm" for a smaller control size (md is the default).

Accessible labels

The navigation landmark is named “Pagination” by default. Override it with aria-label or labels.navigation. Customize the control labels with labels, or provide getPageAriaLabel for individual page controls. labels supports navigation, first, previous, next, last, ellipsis, and page; page is a function that receives the page number.

API

PropTypeDefaultDescription
totalPagesnumberRequiredTotal number of pages.
pagenumber-Controlled current page; page numbers start at 1.
defaultPagenumber1Initial page when uncontrolled.
onPageChange(page: number) => void-Called when a different page is selected.
siblingCountnumber1Number of adjacent page numbers around the current page.
boundaryCountnumber1Number of page numbers shown at each end.
showFirstLastbooleantrueWhether to show first- and last-page controls.
disabledbooleanfalseDisables navigation controls.
size"sm" | "md""md"Control size.
getPageHref(page: number) => string-Returns a URL to render available pages as links.
getPageAriaLabel(page: number) => string-Returns the accessible label for a page control.
labelsPartial<PaginationLabels>-Accessible labels for navigation, first, previous, next, last, ellipsis, and page controls.
aria-labelstring"Pagination"Accessible name for the navigation landmark; labels.navigation is used when omitted.
classNamestring-Additional class for the navigation landmark.

Other native nav attributes are supported.

Accessibility

  • Pagination renders a labeled navigation landmark containing a list of controls.
  • The current page is identified with aria-current="page" and cannot be selected again.
  • Previous and next controls are disabled at the ends of the page range. Use descriptive custom labels when the defaults do not fit your language or context.
;