# Pagination

> Centred page buttons with previous and next, gaps for long ranges, and a summary line at the left.

Category: Navigation. Docs page: https://rime.mjsons.net/components/pagination

## Installation

```bash
npx shadcn@latest add KezLahd/rime/table
```

Pagination is the pager that sits under every Table, documented on its own because it works under any list: cards, search results, an activity feed. The page buttons stay on the centre line whatever the summary's length (a 1fr auto 1fr grid), and long ranges collapse into gaps around the current page.

With totalItems and pageSize it says "Showing 41 to 60 of 236 orders"; without, "Page 3 of 12". It is presentational: the screen owns the page number.

## Usage

```tsx
import { Pagination } from "@/components/ui";

<Pagination page={page} pageCount={12} onPageChange={setPage} totalItems={236} pageSize={20} itemLabel="orders" />
```

## Props: Pagination

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `page` (required) | `number` |  |  |
| `pageCount` (required) | `number` |  |  |
| `onPageChange` (required) | `(page: number) => void` |  |  |
| `totalItems` | `number` |  |  |
| `pageSize` | `number` |  |  |
| `itemLabel` | `string` | `"results"` | Plural noun for the summary: "customers", "requests". |
| `className` | `string` |  |  |

## Examples

### With a summary

```tsx
<Pagination page={page} pageCount={12} onPageChange={setPage} totalItems={236} pageSize={20} itemLabel="orders" />
```

### Pages only

```tsx
<Pagination page={page} pageCount={5} onPageChange={setPage} />
```

## Theme tokens

Per-component tokens. Undeclared by default: the default below is the fallback the CSS uses. Set any of them at :root or on a wrapper to restyle every instance.

| Token | Default |
| --- | --- |
| `--button-primary-bg` | `var(--brand-gradient)` |
| `--button-radius` | `var(--r-sm)` |
| `--inner-radius` | `var(--r-lg)` |
| `--r-flat` | `var(--table-radius, var(--r-md))` / `var(--table-radius, var(--inner-radius, var(--r-lg)))` |
| `--table-radius` | `var(--r-md)` / `var(--inner-radius, var(--r-lg))` |
| `--table-row-height` | `46px` |

System tokens it reads: `--brand-deep`, `--brand-gradient`, `--control-h-sm`, `--dur`, `--ease`, `--focus-color`, `--focus-ring`, `--font-mono`, `--glass-fill-nested`, `--glow-sm`, `--ink-body`, `--ink-brand`, `--ink-disabled`, `--ink-inverse`, `--ink-muted`, `--line-glass`, `--line-soft`, `--r-lg`, `--r-md`, `--r-sm`, `--rgb-contact`, `--surface-solid`, `--table-cell-pad`, `--table-head-fill`, `--table-head-hover`, `--table-head-ink`, `--table-head-pad`, `--table-head-press`, `--table-head-rule`, `--table-row-hover`, `--table-row-line`, `--text-caption`, `--text-small`, `--wash-subtle`.

## Accessibility

- A nav labelled "Pagination"; the current page button has aria-current="page"; every button is named "Page n".
- Previous and next disable at the ends rather than disappearing, so the layout never jumps.
- The summary is a polite live region, so a page change is announced.

## Do

- Reset to page one when a filter or sort changes.
- Keep it centred under the list it pages.

## Don't

- Don't left-align the page buttons.
- Don't use infinite scroll for records people need to find again.

Related: https://rime.mjsons.net/components/table, https://rime.mjsons.net/components/filter-bar
