Pagination
ProLinks between pages of a list, in Candor's theme: previous, next and numbered pages, with the current page marked aria-current="page" and a labelled navigation landmark. It draws the pages the app passes; it never works out how many there are. A page a person can't go to (before the first, past the last) stays in place, marked and explained.
Version 5.2.0· other versions
This page is for 5.2.0, the current release. An earlier release’s page is the Markdown that release published, so the docs match the version you have installed (candor-lock.json records it).
- 5.1.0
- 5.0.0
- 4.5.0
- 4.4.0
- 4.3.0
- 4.2.0
- 4.1.0
- 4.0.2
- 4.0.1
- 4.0.0
- 3.0.0
- 2.10.0
- 2.9.0
- 2.8.0
- 2.7.0
- 2.6.2
- 2.6.1
- 2.6.0
- 2.5.1
- 2.5.0
- 2.4.0
- 2.3.0
Not in the docs of 1.3.0, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.8.0, 1.8.1, 1.9.0, 1.9.1, 2.0.0, 2.1.0 and 2.2.0: the page came later, or had another name then.
Docs pages weren’t kept for 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0 and 1.2.1: they are kept from 1.3.0 on, and before that only llms.txt was published.
Preview
Loading the preview
Install
First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/pagination
Brings in: button, locale, locked, tokens, utils · npm: @base-ui/react@^1.9.0, lucide-react@^1.67.0
Usage
"use client"
import * as React from "react"
import {
Pagination,
PaginationContent,
PaginationEllipsis,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationPrevious,
PaginationRange,
pageWindow,
} from "@/components/candor/ui/pagination"
// The numbers come from the service: 312 items, 20 to a page. The component never works out a total itself.
const total = 312
const pageSize = 20
const pageCount = Math.ceil(total / pageSize)
export default function Example() {
const [page, setPage] = React.useState(1)
const go = (next: number) => (event: React.MouseEvent) => {
event.preventDefault()
setPage(next)
}
return (
<div className="flex flex-col items-center gap-3">
<PaginationRange from={(page - 1) * pageSize + 1} to={Math.min(page * pageSize, total)} total={total} />
<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationPrevious href="#previous" locked={page === 1 ? "You’re on the first page." : undefined} onClick={go(page - 1)} />
</PaginationItem>
{pageWindow({ page, pageCount }).map((entry) => (
<PaginationItem key={entry}>
{typeof entry === "number" ? (
<PaginationLink href={`#page-${entry}`} page={entry} isActive={entry === page} onClick={go(entry)}>
{entry}
</PaginationLink>
) : (
<PaginationEllipsis />
)}
</PaginationItem>
))}
<PaginationItem>
<PaginationNext href="#next" locked={page === pageCount ? "You’re on the last page." : undefined} onClick={go(page + 1)} />
</PaginationItem>
</PaginationContent>
</Pagination>
</div>
)
}<Pagination>
No props.
Also takes the props of React.ComponentProps<"nav">.
<PaginationContent>
The list inside a Pagination that holds its page links.
No props.
Also takes the props of React.ComponentProps<"ul">.
<PaginationEllipsis>
A "…" for the pages a Pagination leaves out.
No props.
Also takes the props of React.ComponentProps<"span">.
<PaginationItem>
One entry in a PaginationContent.
No props.
Also takes the props of React.ComponentProps<"li">.
<PaginationLink>
A link to one page, marked as the current page when isActive.
| Prop | Type | Default | Description |
|---|---|---|---|
| children | React.ReactNode | undefined | — | The content of the link: the page number, or text and icons. |
| isActive | boolean | undefined | — | Marks this link as the current page: `aria-current="page"` and the outlined look. |
| size | React.ComponentProps<typeof Button>["size"] | undefined | "icon" | The size of the link, as a button's. Defaults to icon, a square for a page number. |
| page | number | undefined | — | The page this link goes to, used to name it ("Page 3") for screen readers when it has no `aria-label`. |
| render | useRender.RenderProp | undefined | — | Draws this element (a router link, say) with the link's styles instead of an <a>: `render={<Link href="?page=3" />}`. The element keeps its own children unless the link is given some. |
| locked | string | null | undefined | — | Why the person can't go to this page right now ("You're on the first page."). When set, the link stays focusable and marked `aria-disabled`, following it does nothing, and the reason is shown on hover and focus and read to screen readers (see `Locked`). `null` or left out: unlocked. |
Also takes the props of Omit<React.ComponentProps<"a">, "children">.
<PaginationNext>
The link to the next page in a Pagination.
No props.
Also takes the props of Omit<PaginationLinkProps, "size" | "children">.
<PaginationPrevious>
The link to the previous page in a Pagination.
No props.
Also takes the props of Omit<PaginationLinkProps, "size" | "children">.
<PaginationRange>
Says which items the page shows, from the numbers the app has: "Showing 21–40 of 312". When the total isn't known (a cursor-paged list) it says "Showing 21–40" and nothing about how many there are; it never estimates one.
| Prop | Type | Default | Description |
|---|---|---|---|
| fromrequired | number | — | The position of the first item on this page, counting from 1. |
| torequired | number | — | The position of the last item on this page. |
| total | number | undefined | — | How many items there are in all, when the service has said. Left out, nothing is claimed about the total. |
Also takes the props of Omit<React.ComponentProps<"p">, "children">.
Functions
pageWindow({ page, pageCount, siblings = 1 }: { page: number; pageCount: number; siblings?: number | undefined })The page numbers to draw for a list of pageCount pages with page current: the first and last page, the current page and siblings pages either side, and an ellipsis marker where pages are left out. Never more entries than it needs, and always exactly the pages that exist. Call it from a client component; it is a plain function with no state, so its output is for the app to render with PaginationLink.
Strings
The fixed words, in English by default. Change any of them under pagination in <LocaleProvider strings={{ … }}>; the table is exported as paginationStrings.
| Key | English |
|---|---|
| label | Pagination |
| previous | Previous |
| next | Next |
| previousPage | Go to previous page |
| nextPage | Go to next page |
| page | Page {page} |
| morePages | More pages |
| range | Showing {from}–{to} of {total} |
| rangeOpen | Showing {from}–{to} |
| none | Nothing to show |
Motion
| Moment | Family | What it does |
|---|---|---|
| tint | tint | The current page's colours change when the person moves to another page. The page that is current when the pagination first appears is drawn current at once. |
Set with --cd-motion-pagination-<moment>-* in your brand file; the families are in the design reference.