# Pagination

Navigation for a paginated list or table with page numbers and prev/next controls.

## Installation

```tsx
import { Pagination } from "@makeplane/propel/components/pagination";
```
## Usage

```tsx
import { Pagination } from "@makeplane/propel/components/pagination";
import * as React from "react";

export default function BasicDemo() {
  const [page, setPage] = React.useState(1);

  return <Pagination page={page} pageCount={25} onPageChange={setPage} />;
}
```
## Examples

### With selector and range

Pass `pageSize` to add the per-page selector and `range` to show the `1-50 of 250` label before the controls; both are optional.

```tsx
import { Pagination } from "@makeplane/propel/components/pagination";
import * as React from "react";

export default function WithSelectorAndRangeDemo() {
  const [page, setPage] = React.useState(1);
  const [pageSize, setPageSize] = React.useState(50);

  return (
    <Pagination
      page={page}
      pageCount={5}
      onPageChange={setPage}
      pageSize={{ value: pageSize, options: [25, 50, 100], onValueChange: setPageSize }}
      range={{ current: "1-50", total: 250 }}
    />
  );
}
```

### Truncation

The visible page window is derived from where the current page sits within `pageCount` — first and last are always anchored, and runs of two or more skipped pages collapse to an ellipsis.

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

export default function TruncationDemo() {
  return (
    <div className="flex flex-col gap-4">
      <Pagination
        page={1}
        pageCount={5}
        onPageChange={() => {}}
        labels={{ root: "All pages visible" }}
      />
      <Pagination
        page={1}
        pageCount={100}
        onPageChange={() => {}}
        labels={{ root: "Near start" }}
      />
      <Pagination page={45} pageCount={100} onPageChange={() => {}} labels={{ root: "Middle" }} />
      <Pagination
        page={100}
        pageCount={100}
        onPageChange={() => {}}
        labels={{ root: "Near end" }}
      />
    </div>
  );
}
```

### Empty state

When there's nothing to page through (`pageCount` is `0` or `1`), prefer not rendering `Pagination`
at all. If `pageCount` is `0`, the control still renders safely — no page-number button, both
arrows disabled — rather than showing a stray "page 1".

### Loading

Set `loading` to render the current page as a spinner while navigating to it is in flight.

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

export default function LoadingDemo() {
  return <Pagination page={3} pageCount={25} onPageChange={() => {}} loading />;
}
```

### Labels

`labels` overrides the default English accessible names (landmark, prev/next, page buttons) and the selector's visible text — pass any subset; the rest keep their defaults.

```tsx
import { Pagination } from "@makeplane/propel/components/pagination";
import * as React from "react";

export default function LabelsDemo() {
  const [page, setPage] = React.useState(1);
  const [pageSize, setPageSize] = React.useState(50);

  return (
    <Pagination
      page={page}
      pageCount={5}
      onPageChange={setPage}
      pageSize={{ value: pageSize, options: [25, 50, 100], onValueChange: setPageSize }}
      labels={{
        root: "Work item pages",
        previous: "Previous page",
        next: "Next page",
        page: (pageNumber) => `Page ${pageNumber}`,
        perPage: "rows per page",
      }}
    />
  );
}
```
## API Reference

### Pagination

Page navigation for a paginated list or table. Renders a `<nav>` landmark holding an optional
per-page selector and range label plus an ordered list of page controls: a previous button,
first/last anchors with ellipses around a window of pages near the current one, and a next
button. The current page is marked `aria-current="page"`; the prev/next ends disable at the
bounds and their arrows mirror under RTL.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `page` (required) | `number` | — | The current page, 1-based. |
| `pageCount` (required) | `number` | — | Total number of pages. |
| `onPageChange` (required) | `(page: number) => void` | — | Called with the target page (1-based) when a control is activated. |
| `loading` | `boolean` | `false` | The current page is rendered as a loading spinner instead of its number — for when navigating to that page is in flight. |
| `pageSize` | `{ value: number; options: number[]; onValueChange: (pageSize: number) => void; }` | — | Optional per-page size selector (Figma `50 v per page`). Provide `value`, the `options`, and `onValueChange`; omit to hide the selector entirely. |
| `range` | `{ current: ReactNode; total: ReactNode; }` | — | Optional range label shown before the controls (Figma `1-50 of 250`). Provide the already-formatted `current` range and `total`. |
| `labels` | `Partial<PaginationLabels>` | — | Override the default English accessible names / visible selector text. |
