Browse docs
Browse docs
A controlled pagination control. The consumer owns page and
pageSize; the component emits onPageChange / onPageSizeChange
and recomputes the visible page range from totalCount.
import { Pagination } from '@dashforge/tw';
import { useState } from 'react';
function MyList() {
const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(20);
return (
<Pagination
page={page}
pageSize={pageSize}
totalCount={1437}
onPageChange={setPage}
onPageSizeChange={setPageSize}
/>
);
}<Pagination variant="default" {...props} /> // full kit
<Pagination variant="compact" {...props} /> // page numbers + nav only
<Pagination variant="minimal" {...props} /> // "Page X of Y" + prev/nextvariant | Renders |
|---|---|
default (default) | Summary · page numbers · first/prev/next/last · page-size selector · jump input |
compact | Page numbers · first/prev/next/last only — no summary, no selector, no jump |
minimal | "Page X of Y" text · prev/next only — for narrow surfaces (mobile, dense toolbars) |
<Pagination size="sm" {...props} />
<Pagination size="md" {...props} /> // default
<Pagination size="lg" {...props} />Drives padding + text size on every interactive element. Pick the size that visually balances the table or list it's attached to.
| Prop | Type | Notes |
|---|---|---|
page | number | 1-indexed. The component clamps out-of-range values internally (e.g. page=99 on a 5-page set renders page 5). |
pageSize | number | Items per page. |
totalCount | number | Total items in the underlying data set. NOT total pages — we compute that from totalCount / pageSize. |
onPageChange | (page: number) => void | Fires on every page interaction (button click, jump input commit). |
<Pagination
page={page}
pageSize={pageSize}
totalCount={totalCount}
onPageChange={setPage}
onPageSizeChange={setPageSize} // omit to hide the selector
pageSizeOptions={[10, 20, 50, 100]} // default
siblingCount={1} // pages shown each side of current
boundaryCount={1} // pages always shown at start/end
showFirstLast // default true
showJumpInput // default true (default variant only)
disabled={false} // disables all interactive bits
/>If the total set is small enough to fit within
2 * boundaryCount + 2 * siblingCount + 3 pages, no ellipsis is
shown — every page button renders explicitly. So with defaults
(siblingCount=1, boundaryCount=1), totals of ≤ 7 pages render
all numbers directly; 8+ pages get the ellipsis layout.
All visible strings are configurable via labels. Pass the subset
you need; the rest fall back to English defaults.
<Pagination
page={page}
pageSize={pageSize}
totalCount={250}
onPageChange={setPage}
labels={{
first: 'Inizio',
prev: 'Indietro',
next: 'Avanti',
last: 'Fine',
page: 'Pagina',
of: 'di',
showing: 'Mostrando',
perPage: 'per pagina',
goToPage: 'Vai a pagina',
}}
/>Default English labels:
| Key | Default | Used in |
|---|---|---|
first | 'First' | aria-label of « button |
prev | 'Previous' | aria-label of ‹ button |
next | 'Next' | aria-label of › button |
last | 'Last' | aria-label of » button |
page | 'Page' | "Page N" aria-label + minimal-mode summary |
of | 'of' | "Showing X-Y of Z" + minimal "Page X of Y" |
showing | 'Showing' | Default-variant summary prefix |
perPage | 'per page' | Page-size selector label |
goToPage | 'Go to page' | Jump input placeholder + label |
<nav aria-label="Pagination"> — screen
reader announces it as a pagination navigation region.aria-current="page" so screen
readers announce the current position.aria-label
(page number, "Previous", "Next", "First", "Last", "Go to page").<select> element — native a11y
semantics (arrow keys, Enter, screen reader announces options).<input type="number"> with min / max
matching the page range. Commits on Enter or blur.In variant="default" the rightmost input lets the user jump to
any page directly:
<Pagination
page={page}
pageSize={pageSize}
totalCount={1437}
onPageChange={setPage}
showJumpInput // default; pass `false` to hide
/>Behavior:
[1, totalPages]<Pagination> is fully controlled by design — the same page
pageSize state can drive both a <Pagination> UI and the
underlying list / table. Sprint 4.1 will ship a Table + DataGrid
that explicitly compose with Pagination via the same controlled
state.const [page, setPage] = useState(1);
const [pageSize, setPageSize] = useState(20);
const paginatedRows = useMemo(
() => allRows.slice((page - 1) * pageSize, page * pageSize),
[allRows, page, pageSize],
);
return (
<>
{/* Sprint 4.1 — Table coming */}
<YourList rows={paginatedRows} />
<Pagination
page={page}
pageSize={pageSize}
totalCount={allRows.length}
onPageChange={setPage}
onPageSizeChange={setPageSize}
/>
</>
);Pagination follows the same sx + slotProps dual-override
pattern as every other @dashforge/tw component. See the
Customization guide for the
full decision tree.
sx — outer wrapper<Pagination sx="justify-end gap-6" {...props} />slotPropsAvailable slots: root, summary, list, pageButton,
activeButton, navButton, ellipsis, pageSizeSelector,
jumpInput.
<Pagination
page={page}
pageSize={pageSize}
totalCount={totalCount}
onPageChange={setPage}
slotProps={{
activeButton: { className: 'bg-emerald-600 border-emerald-600' },
summary: { className: 'font-mono uppercase tracking-wide' },
}}
/>| Prop | Type | Default | Notes |
|---|---|---|---|
page | number | — (required) | 1-indexed |
pageSize | number | — (required) | Items per page |
totalCount | number | — (required) | Total items |
onPageChange | (page: number) => void | — (required) | Page navigation handler |
onPageSizeChange | (pageSize: number) => void | — | Omit to hide selector |
variant | 'default' | 'compact' | 'minimal' | 'default' | UI mode |
size | 'sm' | 'md' | 'lg' | 'md' | Visual size |
pageSizeOptions | number[] | [10, 20, 50, 100] | Options shown in selector |
siblingCount | number | 1 | Pages shown each side of current |
boundaryCount | number | 1 | Pages always shown at edges |
showFirstLast | boolean | true | First/Last buttons |
showJumpInput | boolean | true | Direct page-jump input (default variant only) |
disabled | boolean | false | Disables all interactive elements |
labels | PaginationLabels | English defaults | i18n strings |
sx | string | — | Root-level Tailwind override |
slotProps | PaginationSlotProps | — | Per-slot overrides |
sx vs slotProps decision tree