Skip to content
Entangle UI v0.13.0

Pagination

A 1-based page navigator that collapses long page ranges with ellipses. Use it under any list, table, or grid that can be paged through. The MUI-style sibling/boundary algorithm keeps the control compact even for thousands of pages, and the component works in both controlled and uncontrolled modes.

Live Preview

import { Pagination } from 'entangle-ui';

In uncontrolled mode, pass count and (optionally) defaultPage. The component owns the page state and notifies the consumer via onChange.

<Pagination count={20} defaultPage={1} onChange={(_, page) => loadPage(page)} />

For full control, pass page and react in onChange:

const [page, setPage] = useState(1);
<Pagination count={20} page={page} onChange={(_, next) => setPage(next)} />;

Pages are 1-based. count is the total number of pages; pass 0 to render nothing.

Controlled

Three sizes match the rest of the type scale.

Sizes

<Pagination size="sm" count={10} />
<Pagination size="md" count={10} />
<Pagination size="lg" count={10} />

siblingCount controls how many page numbers are shown on each side of the current page. boundaryCount controls how many are pinned to the start and end. Anything skipped collapses into an ellipsis.

Many pages

<Pagination count={50} defaultPage={25} />
// renders: 1 … 24 [25] 26 … 50

Tighter layouts can drop the siblings entirely:

Compact

<Pagination count={20} defaultPage={10} siblingCount={0} boundaryCount={1} />
// renders: ‹ 1 … [10] … 20 ›

For tables with many pages, surface “jump to first” and “jump to last” controls explicitly.

Full controls

<Pagination count={50} defaultPage={25} showFirstButton showLastButton />

Conversely, hide the prev/next controls in compact contexts:

<Pagination count={10} hidePrevButton hideNextButton />

Use disabled to lock the whole control while the consumer is in a transitional state (e.g. fetching a page).

Disabled

<Pagination count={10} defaultPage={4} disabled />

Override the aria-labels for each item type with getItemAriaLabel. Useful for non-English UIs.

<Pagination
count={20}
getItemAriaLabel={(type, page, selected) => {
if (type === 'previous') return 'Strona poprzednia';
if (type === 'next') return 'Strona następna';
if (type === 'first') return 'Pierwsza strona';
if (type === 'last') return 'Ostatnia strona';
if (type === 'page')
return selected ? `Strona ${page}` : `Idź do strony ${page}`;
return 'Więcej stron';
}}
/>
  • The root is a <nav aria-label="pagination"> so screen readers announce it as a navigation region.
  • The current page has aria-current="page".
  • Each button has a descriptive aria-label (Go to page 5, Go to next page, etc.) — customise with getItemAriaLabel.
  • Disabled state is conveyed via the native disabled attribute on the button.
  • Ellipses are decorative and use aria-hidden="true".
  • Buttons are keyboard-reachable in the default tab order; Enter and Space activate them.
Prop Type Default Description
count number Total number of pages.
page number Currently selected page (1-based). Controls the component when set.
defaultPage number 1 Default selected page in uncontrolled mode (1-based).
onChange (event: SyntheticEvent, page: number) => void Called when the user requests a new page.
siblingCount number 1 Pages shown on each side of the current page.
boundaryCount number 1 Pages always shown at the start and end of the list.
showFirstButton boolean false Show the "jump to first" button.
showLastButton boolean false Show the "jump to last" button.
hidePrevButton boolean false Hide the previous-page button.
hideNextButton boolean false Hide the next-page button.
size 'sm' | 'md' | 'lg' 'md' Visual size.
disabled boolean false Disable the whole control.
getItemAriaLabel (type, page, selected) => string Custom aria-label generator for each item.