<!-- Generated by scripts/gen-docs.mts from the JSDoc in registry/. Do not edit; run `pnpm run docs`. -->

# Pagination

Page navigation for a long list: Previous, the page numbers with gaps, and Next, with the current page marked `aria-current="page"`. With `href` every page is a real link, so it works with no JavaScript and through your router; with `onPageChange` the pages are buttons. Below 640px the numbers give way to "Page 3 of 12" between Previous and Next. Without `pageCount`, for a list that is not counted, it shows Previous and Next only, and `hasNextPage` enables Next.

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

## Example

```tsx
<Pagination page={3} pageCount={12} href="/recipes?page={page}" />
<Pagination page={page} pageCount={12} onPageChange={setPage} />
<Pagination page={page} hasNextPage={rows.length > pageSize} href="?page={page}" />
```

## Usage

Use `Tabs` to switch between a few named views.

## Use instead when

- Use `ShowMore` instead when the next rows should join the list in place.

## Props

The props the modes share. Type: `PaginationProps`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `className` | `string` |  | Layout only: margins, width, grid placement (`mt-6`). Appearance classes warn in development. |
| `label` | `string` | `"Pagination"` | Names the navigation for screen readers. |
| `nextLabel` | `string` | `"Next"` | The text of the link to the page after. |
| `page` (required) | `number` |  | The current page, counting from 1. |
| `pageLabel` | `string` | `"Page {page}"` | What a screen reader calls each page number; `{page}` is the number. |
| `previousLabel` | `string` | `"Previous"` | The text of the link to the page before. |
| `ref` | `Ref<HTMLElement>` |  | Reaches the rendered element. |
| `siblings` | `number` | `1` | How many pages show on each side of the current one before a gap ("1 … 4 5 6 … 12" is `1`). The list keeps the same number of cells on every page, so Next never moves. |
| `summaryLabel` | `string` | `"Page {page} of {pageCount}"` | The text between Previous and Next below 640px, where the page numbers do not fit; `{page}` and `{pageCount}` are the numbers. |

## Modes

`PaginationProps` is a union: pass the props of exactly one mode. Mixing them is a type error.

### With `href` and `hasNextPage`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `hasNextPage` | `boolean` | `false` | Whether there is a page after this one, which enables Next. |
| `href` (required) | `string \| ((page: number) => string)` |  | The address of a page: a string with `{page}` (`href="/recipes?page={page}"`, which a Server Component can pass) or a function (`href={(page) => `/recipes?page=${page}`}`). Internal paths go through `OuroProvider`'s `linkComponent`, so your router navigates. |

Not in this mode (typed `never`):

- `onPageChange`: Not with `href`. Remove `href` to render buttons that call `onPageChange`.
- `pageCount`: Leave it out when the list has no count; pass it to show the page numbers.

### With `href` and `pageCount`

| Prop | Type | Description |
| --- | --- | --- |
| `href` (required) | `string \| ((page: number) => string)` | The address of a page: a string with `{page}` (`href="/recipes?page={page}"`, which a Server Component can pass) or a function (`href={(page) => `/recipes?page=${page}`}`). Internal paths go through `OuroProvider`'s `linkComponent`, so your router navigates. |
| `pageCount` (required) | `number` | How many pages there are. From a count of rows: `Math.ceil(total / pageSize)`. |

Not in this mode (typed `never`):

- `hasNextPage`: Not with `pageCount`, which decides whether there is a next page.
- `onPageChange`: Not with `href`. Remove `href` to render buttons that call `onPageChange`.

### With `onPageChange` and `hasNextPage`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `hasNextPage` | `boolean` | `false` | Whether there is a page after this one, which enables Next. |
| `onPageChange` (required) | `(page: number) => void` |  | Called with the page number when the person picks a page. Update `page` in it. |

Not in this mode (typed `never`):

- `href`: Not with `onPageChange`. Remove `onPageChange` to render links.
- `pageCount`: Leave it out when the list has no count; pass it to show the page numbers.

### With `onPageChange` and `pageCount`

| Prop | Type | Description |
| --- | --- | --- |
| `onPageChange` (required) | `(page: number) => void` | Called with the page number when the person picks a page. Update `page` in it. |
| `pageCount` (required) | `number` | How many pages there are. From a count of rows: `Math.ceil(total / pageSize)`. |

Not in this mode (typed `never`):

- `hasNextPage`: Not with `pageCount`, which decides whether there is a next page.
- `href`: Not with `onPageChange`. Remove `onPageChange` to render links.

## Don't use

These are not props. Passing one fails the type check with the fix in the error, and in development a console message names the fix.

- `count`: Not a prop. Ouro UI uses `pageCount`: `<Pagination page={1} pageCount={12}>`.
- `currentPage`: Not a prop. Ouro UI uses `page`, counting from 1: `<Pagination page={1} pageCount={12}>`.
- `onChange`: Not a prop. Ouro UI uses `onPageChange`, which gets the page number: `onPageChange={(page) => …}`.
- `total`: Not a prop. Pass the number of pages: `pageCount={Math.ceil(total / pageSize)}`.
- `totalPages`: Not a prop. Ouro UI uses `pageCount`: `<Pagination page={1} pageCount={12}>`.

## `className` is for layout only

Pass margins, width and grid placement (`mt-4`, `w-full`, `col-span-2`).

Appearance comes from props, not classes. In development, a class that sets appearance logs one warning per component instance, naming the prop to use instead. A class sets appearance when, after its variants (`hover:`, `sm:`) and any `!` are removed, it starts with `bg-`, `text-`, `border-`, `rounded-`, `shadow-`, `font-`, `ring-`, `from-`, `via-`, `to-`, `fill-` or `stroke-`, or is `border`, `rounded`, `shadow` or `ring`, or has a `dark:` variant. Text wrapping, overflow and table layout classes (`text-wrap`, `text-ellipsis`, `border-collapse`) are layout and do not warn.

Alignment classes (`text-center`) warn too: set alignment on a parent element.
