Page controls for long tables — windowed numbers with ellipses.
Anatomy
‹ 1 … 6 7 8 … 24 › │ │ │ └─┬─┘ │ └ next (disabled on last) │ │ │ └ current ±siblings │ │ └ ellipsis (aria-hidden) │ └ first page — always visible └ prev (disabled on first)
Props
| Prop | Type | Default | Notes |
|---|---|---|---|
page | number | — | Current page, 1-based. |
count | number | — | Total pages. |
onPageChange | (page: number) => void | — | Fires for numbers and ‹/›. |
siblings | number | 1 | Pages shown each side of current. |
className | string | — | cn-merged onto the nav. |
Motion
150ms on background/color only. Page changes re-render the window
instantly — no sliding.
A11y
<nav aria-label="Pagination"> with a list of real buttons — 40px hit
targets (h-10/min-w-10). Prev/next carry explicit labels ("Previous
page"/"Next page"); the current page is aria-current="page".
Callback-driven: if pages are URLs in your app, wrap in links at the
call site instead.