← Back to home

Pagination

An accessible pagination component supporting both numeric page navigation (offset mode) and cursor-based pagination.

Usage

tsx
import { useState } from 'react';
import { Pagination } from '@components-kit/react';

const fetchNext = () => {};
const fetchPrevious = () => {};
const fetchFirst = () => {};
const fetchLast = () => {};

// Basic offset mode (uncontrolled)
<Pagination totalPages={10} defaultPage={1} />

// Controlled offset mode
function ControlledPagination() {
  const [page, setPage] = useState(1);

  return <Pagination totalPages={10} page={page} onPageChange={setPage} />;
}

// With custom siblings
<Pagination totalPages={20} defaultPage={10} siblings={2} />

// With first/last buttons
<Pagination totalPages={50} defaultPage={1} showFirstLast />

// Cursor-based mode
<Pagination
  hasNextPage={data.hasNext}
  hasPreviousPage={data.hasPrevious}
  onNext={() => fetchNext()}
  onPrevious={() => fetchPrevious()}
/>

// Cursor mode with first/last buttons
<Pagination
  hasNextPage={true}
  hasPreviousPage={true}
  onNext={() => fetchNext()}
  onPrevious={() => fetchPrevious()}
  showFirstLast
  onFirst={() => fetchFirst()}
  onLast={() => fetchLast()}
/>

// Disabled
<Pagination totalPages={10} defaultPage={3} disabled />

// With variant
<Pagination totalPages={10} defaultPage={1} variantName="compact" />

Props

PropTypeDefaultDescription
totalPagesnumber-Total pages. Enables offset mode when provided.
pagenumber-Controlled current page (1-based)
defaultPagenumber1Initial page for uncontrolled mode
onPageChange(page: number) => void-Callback on page change (offset mode)
siblingsnumber1Sibling pages on each side of current
disabledboolean-Disables all buttons
showFirstLastbooleanfalseShow first/last navigation buttons
variantNameVariantFor<"pagination">-Variant name for styling
hasNextPageboolean-Next page available (cursor mode)
hasPreviousPageboolean-Previous page available (cursor mode)
onNext() => void-Next callback (cursor mode)
onPrevious() => void-Previous callback (cursor mode)
onFirst() => void-First callback (both modes)
onLast() => void-Last callback (both modes)
hasFirstPageboolean-First page available (cursor mode, defaults to hasPreviousPage)
hasLastPageboolean-Last page available (cursor mode, defaults to hasNextPage)

Also accepts all standard nav HTML attributes.

Data Attributes

AttributeApplied OnValuesDescription
data-ck="pagination"Root"pagination"Component identifier
data-modeRoot"offset", "cursor"Current pagination mode
data-variantRootstringVariant name for styling
data-disabledRoot, buttonstruePresent when disabled
data-ck="pagination-list"List"pagination-list"Button list container
data-ck="pagination-page"Page button"pagination-page"Page number button
data-ck="pagination-previous"Prev button"pagination-previous"Previous navigation button
data-ck="pagination-next"Next button"pagination-next"Next navigation button
data-ck="pagination-first"First button"pagination-first"First navigation button
data-ck="pagination-last"Last button"pagination-last"Last navigation button
data-ck="pagination-ellipsis"Ellipsis"pagination-ellipsis"Truncation indicator
data-statePage button"active", "inactive"Current page state
data-slot="page-item"List items"page-item"Structural slot

Accessibility

Uses <nav> landmark with aria-label="Pagination" following the WAI-ARIA navigation landmark pattern.

ARIA Attributes

  • Current page: aria-current="page" marks the active page button
  • Page labels: "Page N, current page" or "Go to page N" for descriptive identification
  • Navigation labels: "Go to previous page", "Go to next page", "Go to first page", "Go to last page"
  • Disabled: aria-disabled="true" keeps buttons focusable for assistive technology
  • Ellipsis: aria-hidden="true" hides decorative truncation indicators

Keyboard Support

KeyAction
Tab / Shift+TabMove focus between pagination buttons
EnterActivate the focused button
SpaceActivate the focused button

WCAG 2.2 AA Compliance

CriterionLevelRequirement
2.1.1 KeyboardAAll buttons keyboard-operable
2.4.3 Focus OrderALogical DOM focus sequence
2.5.8 Target SizeAAEnsure minimum 24x24px button targets
1.4.3 ContrastAAEnsure 4.5:1 text contrast ratio
4.1.2 Name, Role, ValueAAll buttons have accessible names and roles

Best Practices

  • Use offset mode when the total page count is known
  • Use cursor mode for infinite scroll or streaming data patterns
  • Provide a unique aria-label when multiple pagination components exist on the same page
  • Ensure button targets are at minimum 24x24 CSS pixels (WCAG 2.5.8)
  • Ensure sufficient color contrast between active/inactive states (WCAG 1.4.3)
  • After dynamic page load, manage focus to the new content area in your application