Pagination
ImplementedPage-number navigator with prev/next — button pager by default, <a href> SEO mode via href. Computes totalPages from totalItems/pageSize and hides itself when there is ≤1 page.
patterns/molecules/pagination.htmlWindowed page navigator with first/prev/next/last edges and an optional page-size row. Composes the PageSizeDropdown atom. Renders real anchors in href (SEO) mode; renders null when there is one page or fewer.
Pagination
molecules
Button-driven pager by default: windowed page numbers (1 … current-1/current/current+1 … N) with ellipses, 44px tap targets, and a "Showing N out of M" size row. Pass href(page) to render crawlable <a> links.
Props
Pagination
currentPagenumber—1-based; clamped into [1, ceil(totalItems/pageSize)]
onPageChange(page: number) => void—Fires on page clicks (also in href mode, on plain clicks).
totalItemsnumber—Total item count — totalPages is derived, not passed.
pageSizenumber—Items per page.
onPageSizeChange(size: number) => void—Fires from the page-size dropdown (requires showPageSize).
pageSizeOptionsnumber[]—Choices offered in the page-size dropdown.
showPageSizebooleantrueRenders the PageSizeDropdown row.
ariaLabelstring'Pagination'Accessible name of the nav landmark — pass a localized value.
href(page: number) => string—Link-based SEO pager mode — page controls render as <a href> anchors. onPageChange still fires on plain click; modifier clicks keep native behaviour.
labelsPaginationLabels—i18n label overrides (goToPage, currentPage, showing, outOf, itemsPerPage, sizeSummary + edge labels). {page}/{total}/{size} placeholders substituted. Under next-intl the 4 placeholder keys MUST be sourced via t.raw().
classNamestring—Additional CSS classes on the nav.
idstring—Stable root id.
<Pagination />Accessibility
Type
1 ruleARIA
1 ruleUsage
Import
import { Pagination } from "@epasslive/design-system"Example 1
<Pagination totalItems={128} pageSize={8} currentPage={3} onPageChange={setPage} />Example 2
<Pagination totalItems={128} pageSize={8} currentPage={page} onPageChange={setPage} href={(p) => `/events?page=${p}`} labels={paginationLabels} />Anti-patterns
— Do not pass totalPages — it is derived from totalItems/pageSize
— Do not use plain t() on placeholder-bearing pagination label keys (next-intl FORMATTING_ERROR); use t.raw()
— Do not use ICU plurals/selects in pagination.* label keys — fill() only substitutes simple {name} placeholders