Skip to content

Navigation

Pagination

A navigation landmark that exposes the current page and page controls.

When to use it: Use it to move between discrete pages of results, not to load more content in place.

On this page

Example

Pagination.tsxtsx
import {
  Pagination,
  PaginationEllipsis,
  PaginationFirst,
  PaginationItem,
  PaginationLast,
  PaginationList,
  PaginationNext,
  PaginationPage,
  PaginationPrevious,
} from "@comp0/react";

export function Example() {
  return (
    <Pagination defaultPage={6} totalPages={20}>
      {({ pages }) => (
        <PaginationList className="flex items-center gap-1">
          <PaginationItem>
            <PaginationFirst className="rounded px-2.5 py-2 text-sm hover:bg-zinc-100 disabled:opacity-40 dark:hover:bg-zinc-800">
              First
            </PaginationFirst>
          </PaginationItem>
          <PaginationItem>
            <PaginationPrevious className="rounded px-2.5 py-2 text-sm hover:bg-zinc-100 disabled:opacity-40 dark:hover:bg-zinc-800">
              Previous
            </PaginationPrevious>
          </PaginationItem>
          {pages.map((entry) => (
            <PaginationItem key={entry}>
              {typeof entry === "number" ? (
                <PaginationPage
                  page={entry}
                  className="size-9 rounded text-sm hover:bg-zinc-100 data-current:bg-zinc-900 data-current:text-white dark:hover:bg-zinc-800 dark:data-current:bg-zinc-100 dark:data-current:text-zinc-950"
                >
                  {entry}
                </PaginationPage>
              ) : (
                <PaginationEllipsis className="grid size-9 place-items-center text-zinc-500" />
              )}
            </PaginationItem>
          ))}
          <PaginationItem>
            <PaginationNext className="rounded px-2.5 py-2 text-sm hover:bg-zinc-100 disabled:opacity-40 dark:hover:bg-zinc-800">
              Next
            </PaginationNext>
          </PaginationItem>
          <PaginationItem>
            <PaginationLast className="rounded px-2.5 py-2 text-sm hover:bg-zinc-100 disabled:opacity-40 dark:hover:bg-zinc-800">
              Last
            </PaginationLast>
          </PaginationItem>
        </PaginationList>
      )}
    </Pagination>
  );
}

Anatomy

Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.

A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.

  1. Pagination

    Native navigation landmark that owns the current page and visible page range. Owns a DOM element.

  2. PaginationList

    Native ul for the controls. Owns a DOM element.

  3. PaginationItem

    Native li wrapping one control or ellipsis. Owns a DOM element.

  4. PaginationPage

    Button or link that selects a numbered page. Owns a DOM element.

  5. PaginationPrevious / PaginationNextOptional

    Move one page and disable at their bounds. Owns a DOM element.

  6. PaginationFirst / PaginationLastOptional

    Move to the first or last page and disable at their bounds. Owns a DOM element.

  7. PaginationEllipsisOptional

    Presentational omission marker hidden from assistive technology. Owns a DOM element.

Step by step

  1. 1

    Add the main part

    Start Pagination with totalPages and render its pages state in a PaginationList.

  2. 2

    Add the supporting parts

    Wrap every control or generated page in PaginationItem; render ellipsis entries with PaginationEllipsis.

  3. 3

    Make the behavior clear

    Use page and onChange for controlled navigation, or defaultPage for an initial page; previous and next controls disable at their bounds.

    Exampletsx
    <Pagination totalPages={20}>
      {({ pages }) => (
        <PaginationList>
          {pages.map((page) => (
            <PaginationItem key={page}>
              {typeof page === "number" ? (
                <PaginationPage page={page}>{page}</PaginationPage>
              ) : (
                <PaginationEllipsis />
              )}
            </PaginationItem>
          ))}
        </PaginationList>
      )}
    </Pagination>;

Keyboard

Moves through the available page controls.
Selects the focused page or direction.
Space
Selects the focused page or direction.

Forms and accessibility

Pagination changes application navigation state and does not create form values.

Accessibility checklist

  • Use a navigation label that distinguishes this pagination from other page navigation.
  • PaginationPage marks the current page with aria-current=page; do not duplicate that state manually.
  • Ellipses are hidden from assistive technology, so expose only real reachable page controls.

API reference

Importtsx
import { Pagination, PaginationEllipsis, PaginationFirst, PaginationItem, PaginationLast, PaginationList, PaginationNext, PaginationPage, PaginationPrevious } from "@comp0/react";

Pagination

DOM element

Native navigation landmark that owns the current page and visible page range.

PropTypeDescription
pagenumberControlled one-based page.
defaultPagenumberInitial one-based page.
onChange(page: number) => voidReceives the next clamped page.
totalPagesnumberRequired positive number of pages.
siblingCountnumberHow many neighboring and edge pages stay visible.
boundaryCountnumberHow many neighboring and edge pages stay visible.
aria-labelstringNavigation name; defaults to "Pagination".

PaginationList

DOM element

Native ul for the controls.

PaginationItem

DOM element

Native li wrapping one control or ellipsis.

PaginationPage

DOM element

Button or link that selects a numbered page.

PropTypeDescription
pagenumberThe one-based page to select.
asElementTypeRenders a router-style link while keeping pagination behavior.

PaginationPrevious / PaginationNext

OptionalDOM element

Move one page and disable at their bounds.

PaginationFirst / PaginationLast

OptionalDOM element

Move to the first or last page and disable at their bounds.

PaginationEllipsis

OptionalDOM element

Presentational omission marker hidden from assistive technology.

Style hooks

Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.

Pagination

Style hookMeaning
[data-page]The current one-based page.
[data-first]The current page is at a boundary.
[data-last]The current page is at a boundary.

PaginationPage

Style hookMeaning
[data-current]This page is current.

PaginationPrevious / PaginationNext

Style hookMeaning
:disabledThat direction is unavailable.

PaginationFirst / PaginationLast

Style hookMeaning
:disabledThat direction is unavailable.

Keep exploring