Skip to content

Pagination

Moves between pages of a long list.

Library
What’s this?

Installation

pnpm dlx shadcn@latest add @wisty/pagination

The CLI installs the Radix or Base UI file to match your project, with what it builds on: button.

If your project doesn't have Wisty UI's theme yet, add it once with npx shadcn@latest add @wisty/cosmos. Until then, components keep shadcn's default look. Installation has the details.

When to use

Use it

  • A list or table has more rows than fit on one page, and people move between pages.
  • People need to jump to a page by number, or step to the previous or next one.

Don't use it

  • The list grows as people scroll, as Salesforce's list views do. Use Data table, which loads more rows instead.
  • There are only two or three steps in a flow. Use Path, or buttons.
  • People move between sections of one page. Use Tabs.

Usage

Pagination
└── PaginationContent
    ├── PaginationItem
    │   └── PaginationPrevious
    ├── PaginationItem
    │   └── PaginationLink
    ├── PaginationItem
    │   └── PaginationEllipsis
    └── PaginationItem
        └── PaginationNext

Pagination centers itself in its row. To sit it at the end of a list's footer, beside a count, pass className="mx-0 w-auto":

import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination"
<div className="flex items-center justify-between gap-2">
  <p className="text-muted-foreground">26–50 of 132 accounts</p>
  <Pagination className="mx-0 w-auto">
    <PaginationContent>
      <PaginationItem>
        <PaginationPrevious href="?page=1" />
      </PaginationItem>
      <PaginationItem>
        <PaginationLink href="?page=2" isActive>
          2
        </PaginationLink>
      </PaginationItem>
      <PaginationItem>
        <PaginationNext href="?page=3" />
      </PaginationItem>
    </PaginationContent>
  </Pagination>
</div>

size on a link takes Button's sizes: page numbers default to square icon buttons, and previous and next to default.

API reference

PartBuilt on
Pagination<nav> (opens in a new tab)
PaginationContent<ul> (opens in a new tab)
PaginationItem<li> (opens in a new tab)
PaginationLink<a> (opens in a new tab)
PaginationPreviousPaginationLink
PaginationNextPaginationLink
PaginationEllipsis<span> (opens in a new tab)
PropTypeDefault
isActiveboolean
size"default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg""icon"

PaginationPrevious

PropTypeDefault
isActiveboolean
size"default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg"
textstring"Previous"

PaginationNext

PropTypeDefault
isActiveboolean
size"default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg"
textstring"Next"

SLDS mapping

SLDS has no pagination. This one is built from SLDS buttons, through buttonVariants; the table shows which pages are neutral and which are base buttons. Previous and next are base buttons (slds-button) with a chevron. Page numbers take the link color of labelled SLDS buttons, since a page number is a label. The ellipsis has no SLDS part.

Known gaps:

  • No disabled state for previous or next on the first or last page. Leave the item out instead.
PropValueSLDSNotes
PaginationLink isActivetrueslds-button slds-button_neutralThe current page, with buttonVariants variant "outline".
PaginationLink isActivefalseslds-buttonOther pages, with buttonVariants variant "ghost".

Accessibility

  • Pagination is a navigation landmark named "pagination". Rename it with aria-label when a page has more than one.
  • Previous and next are named "Go to previous page" and "Go to next page" whether or not their text shows. text changes the visible label, not the name.

Responsive behavior

  • The list doesn't wrap. Show fewer page numbers on narrow screens, with an ellipsis for the rest.
  • Below the sm breakpoint, previous and next show only their chevrons.

Rules

  • Mark exactly one page, the current one, with isActive. It sets aria-current="page".
  • Give every link an href that loads that page, so pages open in a new tab and work without JavaScript.
  • Use PaginationEllipsis for skipped pages, not a disabled link.
  • Don't restyle the links with variant or color classes.