# 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.

## 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

### Links

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

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

### Buttons

No URLs: the pages call onPageChange.

```tsx
<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

| Name | Type | Values | Default | Description |
| --- | --- | --- | --- | --- |
| `page` | `number` |  |  | Set on Pagination. The current page, from 1. |
| `pageCount` | `number` |  |  | Set on Pagination. How many pages there are. |
| `onPageChange` | `function` |  |  | Set on Pagination. Called with the page to go to, when the pages are buttons. |
| `siblingCount` | `number` |  | `1` | Set on Pagination. Pages shown on each side of the current one. The first and last page always show. |
| `getHref` | `function` |  |  | 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. |
| `isActive` | `boolean` |  | `false` | Set on PaginationLink in your own layout. Marks the current page. |

## Anatomy

| Part | Description |
| --- | --- |
| `root` | Pagination: a nav named Pagination. With page and pageCount it draws everything below; with children it holds your own PaginationContent. |
| `content` | PaginationContent: the row of items, gap-xs, that wraps. |
| `item` | PaginationItem: one slot in the row. |
| `link` | PaginationLink: a page, an sm ghost Button at least as wide as it is tall, with tabular figures. The current page is secondary. |
| `step` | PaginationPrevious and PaginationNext: sm ghost Buttons with a 16px caret and the words Previous and Next. |
| `ellipsis` | PaginationEllipsis: Tabler DotsThree, 16px, in place of the pages left out. |
| `hitArea` | Transparent ::before on every link, never smaller than size-target-min. |

## Accessibility

Role: `navigation`

| Keys | Action |
| --- | --- |
| `Tab` | Moves through Previous, the pages and Next. |
| `Enter, Space` | Goes 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

```bash
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"`).
