Pagination
Server-safe page links from page and total: previous/next, ellipsis gaps and a sliding active pill, with numbers that swipe the way you moved. Links by default; buttons with onPageChange. The row keeps a fixed width so it never jumps.
Page 6 of 12
import { Pagination } from "@/components/ui/pagination";// Server page: plain links, so paging works without JavaScript.export function PostsPager({ page, total }: { page: number; total: number }) { return ( <Pagination page={page} total={total} href={(p) => `/blog?page=${p}`} /> );}<Pagination>
Page links (or buttons) with previous and next. The active pill slides between pages and the numbers swipe the way you moved. The row keeps its width: gaps become an ellipsis.
page*numberCurrent page, from 1.
total*numberNumber of pages.
hrefdefault(page) => `?page=${page}`(page: number) => stringURL of a page, for links that work without JS. Default
?page=N. Unused withonPageChange.labels{ previous?: ReactNode; next?: ReactNode; }Text of the previous and next controls; phones show the arrows only.
onPageChange(page: number) => voidCalled with the picked page; the controls become buttons. From client parents only.
siblingsdefault1numberPages kept on each side of the current one.
| Prop | Type | Default |
|---|---|---|
page*Current page, from 1. | number | — |
total*Number of pages. | number | — |
hrefURL of a page, for links that work without JS. Default | (page: number) => string | (page) => `?page=${page}` |
labelsText of the previous and next controls; phones show the arrows only. | { previous?: ReactNode; next?: ReactNode; } | — |
onPageChangeCalled with the picked page; the controls become buttons. From client parents only. | (page: number) => void | — |
siblingsPages kept on each side of the current one. | number | 1 |
Also accepts every <nav> prop.
pageRange()
Page numbers to render, with "…" for gaps. Keeps first, last and siblings pages on each side of page, and always returns the same length so the bar never changes width. Key items by index so each slot stays mounted and its number swipes instead of remounting. E.g. pageRange(6, 12) returns [1, "…", 5, 6, 7, "…", 12].
pageRange(page: number, total: number, siblings?: number) => (number | "…")[]
* required. Every component also takes className.