InfinitiBit Design System

Pagination

Page navigation for paginated data — built from the PageTab atom.

Pagination splits long result sets into pages. It is composed from two pieces: PageTab (a single page number, the selected page, or a truncation ellipsis) and Pagination (the full control with prev/next and the computed page range — see below). The components are stateless: the consumer owns the current page.

Installation

pnpm add @infinitibit_gmbh/ui @infinitibit_gmbh/theme-default

Pagination

The composed control. It is stateless — you own the current page and update it from onPageChange. The page range is computed for you: first and last pages always show, the current page keeps a sibling on each side (siblingCount, default 1), and wide gaps collapse to . Prev/next disable at the bounds.

import { Pagination } from '@infinitibit_gmbh/ui';

function Example() {
  const [page, setPage] = React.useState(1);
  return <Pagination page={page} totalPages={20} onPageChange={setPage} />;
}

API

PropTypeDefaultDescription
pagenumberCurrent page (1-based)
totalPagesnumberTotal number of pages
onPageChange(page: number) => voidCalled with the next page (tab / prev / next)
size'sm' | 'lg''lg'Tab size
siblingCountnumber1Pages shown on each side of the current page
prevIcon / nextIconReactNodechevronsOverride the arrow glyphs
labelstring'Pagination'Accessible label for the nav landmark

For the page-range without the UI, the paginationRange() helper is exported too.

PageTab

A fixed square tab — lg (32px, default) or sm (24px). selected highlights the current page and sets aria-current="page". truncated renders a static, non-interactive .

import { PageTab } from '@infinitibit_gmbh/ui';

<PageTab>1</PageTab>
<PageTab selected>2</PageTab>
<PageTab truncated />

Set asChild to render the tab as your own element — typically an <a> so crawlers can follow each page. The tab styling, props, and ref merge onto the child.

<PageTab asChild selected>
  <a href="/products?page=2">2</a>
</PageTab>

API

PageTab

PropTypeDefaultDescription
size'sm' | 'lg''lg'Square size — 24px / 32px
selectedbooleanfalseCurrent page — highlighted, sets aria-current="page"
truncatedbooleanfalseRender a static, non-interactive (not in tab order)
asChildbooleanfalseRender the child element (e.g. <a>) instead of a <button>

Forwards native <button> props (onClick, disabled, …).

Accessibility

  • The selected tab carries aria-current="page".
  • The truncation is aria-hidden and not focusable — there is nothing to activate.
  • Each tab is keyboard-focusable with a visible :focus-visible ring.

On this page