Skip to content
Components

Pagination

Moves between pages of a long list or table: Previous, the page numbers around the current one, Next. Pages are real links when they have a URL (getHref), or buttons that call onPageChange. They look like small Buttons: ghost, and secondary for the current page.

Preview

Props

  • page
  • pageCount
  • siblingCount
  • isActive
import { Pagination } from "@/components/ui/pagination"

<Pagination page={4} pageCount={12} onPageChange={goToPage} />

Usage

When to use

  • Move between pages of a long list or table, with the total number of pages known.
  • Lists whose pages have a URL, so a page can be shared and reloaded.

When not to use

  • A short list. Show it whole.
  • The steps of a flow.
  • Sections of one page. Use Tabs.

Examples

Each page has a URL, so the pages are real links.

import { Pagination } from "@/components/ui/pagination"

<Pagination page={4} pageCount={12} getHref={pageHref} />

Buttons

No URLs: the pages call onPageChange.

import { Pagination } from "@/components/ui/pagination"

<Pagination page={1} pageCount={5} onPageChange={goToPage} />

Do and don't

Do

  • Give pages a URL with getHref when the list has one, so a page can be shared and reloaded.
  • Keep it under the list it pages, and move focus to the top of the list after a page change.
  • Say how many results there are near the list, not only the page count.
  • When the next page loads from the server, change page in a transition (useTransition) and keep the current rows on screen with Table pending, instead of blanking the list.

Don't

  • Don't use it for the steps of a flow.
  • Don't page a short list; show it whole.
  • Don't change siblingCount between pages of one list; the links would jump.

Props

NameTypeValuesDefaultDescription
pagenumber--Set on Pagination. The current page, from 1.
pageCountnumber--Set on Pagination. How many pages there are.
onPageChangefunction--Set on Pagination. Called with the page to go to, when the pages are buttons.
siblingCountnumber-1Set on Pagination. Pages shown on each side of the current one. The first and last page always show.
getHreffunction--Set on Pagination. Returns the URL of a page: (page) => `?page=${page}`. With it the pages are real links, so they open in a new tab and work without JavaScript.
isActiveboolean-falseSet on PaginationLink in your own layout. Marks the current page.

Anatomy

PartDescription
rootPagination: a nav named Pagination. With page and pageCount it draws everything below; with children it holds your own PaginationContent.
contentPaginationContent: the row of items, gap-xs, that wraps.
itemPaginationItem: one slot in the row.
linkPaginationLink: a page, an sm ghost Button at least as wide as it is tall, with tabular figures. The current page is secondary.
stepPaginationPrevious and PaginationNext: sm ghost Buttons with a 16px caret and the words Previous and Next.
ellipsisPaginationEllipsis: Tabler DotsThree, 16px, in place of the pages left out.
hitAreaTransparent ::before on every link, never smaller than size-target-min.

Accessibility

Role: navigation

KeysAction
TabMoves through Previous, the pages and Next.
Enter, SpaceGoes to that page (Space only on buttons).
  • The nav is named Pagination. Each page is named Page 3, and the current one carries aria-current="page".
  • The current page stands out by its border and fill, not only by color.
  • Previous on the first page and Next on the last are disabled: a button gets disabled, a link loses its href and gets aria-disabled.
  • The ellipsis is decorative; the page numbers around it say where the gap is.
  • Each page link keeps a size-target-min hit area.

Install

npx shadcn add https://werewolf-ui.vercel.app/r/pagination.json

This also adds styles/werewolf.css, the tokens every component uses, and any other component it needs. Import that file once in your root CSS, after @import "tailwindcss", with a path relative to that CSS file (from app/globals.css it is @import "../styles/werewolf.css").