Tinyrack

Pagination

A numbered page navigator for lists that are split across static pages.

Contract

Pages are derived, not enumerated: pass currentPage and totalPages and the component decides which numbers to show. hrefFor maps a page number to a URL, which keeps every cell a real link that works without JavaScript. renderLink injects a router element without coupling the component to routing state.

AxisContract
current pagerenders as text, not a link, and carries aria-current="page"
windowboundaryCount pages stay pinned at each end and siblingCount pages sit on each side of the current page
gapsa gap wider than one page collapses into an ellipsis hidden from assistive tech; a gap of exactly one page renders that page
stepsprevious and next carry rel="prev" and rel="next", and become non-interactive at the first and last page
empty statea single page renders nothing

Install

pnpm add @tinyrack/ui

Scroll inside the code area to read long lines.

Styles

@import '@tinyrack/ui/components/pagination.css';

Scroll inside the code area to read long lines.

Imports

import { TRPagination } from '@tinyrack/ui/components/pagination';

Scroll inside the code area to read long lines.

Playground

Usage

Examples

Raise boundaryCount and siblingCount when the list is long enough that a wider window helps readers jump around. Both default to 1.

API

currentPage and totalPages are required and drive the whole sequence; a currentPage outside the range is clamped. hrefFor(page) is required and returns the URL for a page, so page one can point at an unpaginated path such as /blog/ rather than /blog/page/1/.

boundaryCount sets how many pages stay pinned at each end and siblingCount how many sit on each side of the current page. Set boundaryCount to 0 to drop the pinned ends.

label names the landmark and defaults to Pagination. previousLabel and nextLabel default to Previous and Next. pageLabel(page) builds the accessible name of each page link and defaults to Page {n}; the step links combine it with their direction label. Set all four to localize the control.

renderLink(page, state) receives the target page and a state object carrying current and, for the steps, direction. Use it to compose React Router or another client router without nesting anchors. It is not called for the disabled steps.

getPaginationRange is exported from the same subpath for callers that need the visible sequence without the markup.

The root preserves native nav attributes, className, style, events, and React 19 ref. Styles use Tinyrack semantic color, spacing, and typography tokens, and expose --tr-pagination-radius, --tr-pagination-gap, --tr-pagination-border-color, --tr-pagination-current-background, and --tr-pagination-current-text for per-instance overrides.