Home

Pagination

Previous and Next with page numbers between them, for moving through a long list one page at a time.

ui.paginationcomponents/ui/pagination.tsx

Use case

For the AI

Use it under a long list read page by page: every invoice of the year, a client's order history, a log of activity. The current page is outlined and marked for screen readers; Previous and Next keep their arrows and drop their words on a phone. A list short enough to show whole needs none.

Use it when

  • A table or list longer than a screen, read in pages
  • The page number belongs in the address, so a link or a reload lands on the same page
  • People jump to a page, not only to the next one

Use something else when

  • Going up from a record to its list: Breadcrumb
  • Sections of one record: Tabs

Examples

Code

Import

import {
  Pagination,
  PaginationContent,
  PaginationEllipsis,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination"

Usage

export function InvoicePages({ page }: { page: number }) {
  return (
    <Pagination>
      <PaginationContent>
        <PaginationItem>
          <PaginationPrevious href={`?page=${Math.max(1, page - 1)}`} />
        </PaginationItem>
        {[1, 2, 3].map((n) => (
          <PaginationItem key={n}>
            <PaginationLink href={`?page=${n}`} isActive={page === n}>
              {n}
            </PaginationLink>
          </PaginationItem>
        ))}
        <PaginationItem>
          <PaginationEllipsis />
        </PaginationItem>
        <PaginationItem>
          <PaginationNext href={`?page=${page + 1}`} />
        </PaginationItem>
      </PaginationContent>
    </Pagination>
  )
}

Rules

  • The current page's `PaginationLink` takes `isActive`: it sets `aria-current="page"` and the outlined style.
  • Each link carries an `href` to its page; when the page is held in state instead, call `preventDefault` in `onClick` as the showcase does.
  • Passing `render` to `PaginationLink` drops its button styles, so use `href` and `onClick` rather than a custom element.
  • Keep the page inside its bounds in the handler (`Math.max(1, p - 1)`), and mark a gap in the numbers with `PaginationEllipsis` rather than listing every page.