Equality
Equality

Pagination

Page navigation with items-per-page and result info

View Markdown

Overview

Pagination provides controls for moving through a paginated list: first/last and previous/next buttons, a windowed set of numbered page buttons, an optional “showing X to Y of Z” info line, and an optional items-per-page Select. It is a controlled component — you own the current page and page size, and it calls back when the user changes them.

It does not slice your data; it only renders the controls. Compute the current page’s items yourself from currentPage and itemsPerPage, and pass the counts in. To keep the UI uncluttered when pagination isn’t needed, the component renders nothing when totalItems is at or below the smallest items-per-page option.

totalItems vs. filteredItems

Two counts are required because they serve different purposes:

  • totalItems — the full, unfiltered size of the dataset. Used only to decide whether to render the controls at all.
  • filteredItems — the number of items after any active filtering. Drives the page count, the info text, and the numbered buttons.

When no filtering is applied, pass the same value for both.

Usage

Import the component:

import { Pagination } from "@eqtylab/equality";

Hold the page and page size in state, slice your data from them, and wire the callbacks:

const [currentPage, setCurrentPage] = useState(1);
const [itemsPerPage, setItemsPerPage] = useState(10);

const pageItems = allItems.slice(
  (currentPage - 1) * itemsPerPage,
  currentPage * itemsPerPage,
);

<Pagination
  currentPage={currentPage}
  totalItems={allItems.length}
  filteredItems={allItems.length}
  itemsPerPage={itemsPerPage}
  onPageChange={setCurrentPage}
  onItemsPerPageChange={setItemsPerPage}
  type="items"
/>;

Changing the page size resets to page 1 automatically.

Default

Configuration

  • Items-per-page dropdown — only shown when you pass onItemsPerPageChange. Without it, the info line shows a static end count instead. Customise the choices with itemsPerPageOptions.
  • Info line — set showInfo={false} to hide the “showing X to Y of Z” text. Use type to append a noun (e.g. type="items" → “of 100 items”).
  • First/last jumps — double-chevron buttons bookend the navigation so users can jump straight to the first or last page. They appear only once there are more pages than maxVisiblePages; while every page still has its own numbered button, they would duplicate it. Set showFirstLast={false} to render only previous/next.
  • WindowingmaxVisiblePages controls how many numbered buttons appear at once; the window slides to keep the current page centered.
  • Scroll on change — pass scrollTargetRef (a ref or an element id string) to smooth-scroll that element into view whenever the page changes.

Props

NameDescriptionTypeDefaultRequired
currentPageThe active page (1-based).number
totalItemsFull dataset size. Controls whether the component renders.number
filteredItemsItem count after filtering. Drives page count and info text.number
itemsPerPageNumber of items shown per page.number
onPageChangeCalled with the new page when the user navigates.(page: number) => void
onItemsPerPageChangeCalled with the new page size. When provided, the items-per-page dropdown is shown.(itemsPerPage: number) => void
itemsPerPageOptionsChoices offered in the items-per-page dropdown.number[][10, 25, 50, 100]
showInfoWhether to show the “showing X to Y of Z” info line.booleantrue
showFirstLastWhether to show the jump-to-first and jump-to-last buttons when there are more pages than maxVisiblePages.booleantrue
maxVisiblePagesMaximum number of numbered page buttons shown at once.number5
typeNoun appended to the info line (e.g. "items").string""
scrollTargetRefElement (ref or id string) scrolled into view on page change.RefObject<HTMLElement>, string
classNameAdditional CSS classes applied to the container.string