---
title: Pagination
description: Page navigation for paginated data
visibility: guest
draft: false
---

# Pagination

Navigate through paginated result sets. The component is a thin UI layer over Laravel's [`LengthAwarePaginator`](https://laravel.com/docs/pagination) — pass the paginator instance and the component renders the appropriate navigation controls.

## Basic Usage

In your Livewire component (or controller):

```php
public function render()
{
    return view('livewire.users', [
        'users' => User::paginate(15),
    ]);
}
```

In the Blade view:

```blade
<x-wirekit::pagination :paginator="$users" />
```

The component renders nothing if the paginator only has a single page.

## Variants

### Full (default)

Shows numbered page links, prev/next arrows, and a "Showing X to Y of Z results" summary. Use for long lists where jumping to a specific page matters.

:::preview{title="Full variant (default)"}
<x-wirekit::pagination :paginator="$users" />
:::

### Simple

Shows prev/next buttons and a "Page X of Y" label. Ideal for infinite scrolls or when jumping to arbitrary pages is not needed.

:::preview{title="Simple variant"}
<x-wirekit::pagination :paginator="$users" variant="simple" />
:::

### Mini

Just prev/next buttons — the most compact form, useful in tight layouts like sidebar widgets.

:::preview{title="Mini variant"}
<x-wirekit::pagination :paginator="$users" variant="mini" />
:::

## Alignment

The `justify` prop controls how the summary text and page buttons are spread within the container:

:::preview{title="justify=between (default: summary left, pages right)"}
<x-wirekit::pagination :paginator="$users" justify="between" />
:::

:::preview{title="justify=center (everything centered)"}
<x-wirekit::pagination :paginator="$users" justify="center" />
:::

:::preview{title="justify=end (everything right-aligned)"}
<x-wirekit::pagination :paginator="$users" justify="end" />
:::

:::preview{title="justify=start (everything left-aligned)"}
<x-wirekit::pagination :paginator="$users" justify="start" />
:::

The `full` variant with `justify="between"` (default) spreads the "Showing X to Y" summary to the left and page numbers to the right — the most common table layout pattern.

## Width & Layout

The pagination stretches to fill its parent width (`w-full`), which allows `justify="between"` to spread its children apart. Wrap it in a constrained container if you need a narrower pagination area.

## Translation

Every visible string runs through Laravel's `__()`, so the component follows your
app locale with no props to set. WireKit ships no translation files of its own —
the English source strings *are* the keys. Add them to your app's JSON language
files (`lang/de.json`, `lang/fr.json`, …) to translate:

| Key | Where it appears |
|-----|------------------|
| `Pagination` | the nav landmark's `aria-label` |
| `Showing :first to :last of :total results` | the summary line (`full` variant) |
| `Page :current of :last` | the centered label (`simple` variant) |
| `Previous` / `Next` | the prev/next controls and their `aria-label`s |
| `Go to page :page` | each numbered link's `aria-label` |

```json
{
    "Pagination": "Seitennummerierung",
    "Showing :first to :last of :total results": "Zeige :first bis :last von :total Ergebnissen",
    "Page :current of :last": "Seite :current von :last",
    "Previous": "Zurück",
    "Next": "Weiter",
    "Go to page :page": "Gehe zu Seite :page"
}
```

The two sentences are single keys with placeholders rather than assembled from
separate words, so you can reorder them freely — a locale that needs the total
before the range, or a different particle between the numbers, writes exactly
that. The numbers keep their emphasis wherever you move the placeholders.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `paginator` | [`LengthAwarePaginator`](https://laravel.com/api/12.x/Illuminate/Pagination/LengthAwarePaginator.html) | `null` | The Laravel paginator instance (required) |
| `variant` | string | `'full'` | `'full'`, `'simple'`, `'mini'` |
| `justify` | string | `'between'` | Flex layout: `'between'` (summary left, pages right), `'center'`, `'start'`, `'end'` |
| `previous-label` | string | `null` | Word for the backward control. `Previous` is correct on a page-ordered list and misleading on a reverse-chronological one, where moving "next" goes backward in time — on a changelog or an activity feed, `previous-label="Newer"` says what the button does. Leave it unset to keep the translated default. |
| `next-label` | string | `null` | Word for the forward control — the companion to `previous-label`. |
| `scope` | string\|null | `null` | Scoped personalization name |

### Paginator Object Reference

The component reads the following methods/properties from the paginator; all are provided automatically by Laravel's `Model::paginate()` and `DB::table()->paginate()`:

| Accessor | Used for |
| --- | --- |
| `hasPages()` | Early-return when the collection fits on a single page (component renders nothing) |
| `currentPage()` | Highlight the current page with `aria-current="page"` |
| `lastPage()` | Render the "Page X of Y" summary in `simple` variant |
| `firstItem()` / `lastItem()` | Render the "Showing X to Y" range in `full` variant |
| `total()` | Render the "of Z results" total in `full` variant |
| `previousPageUrl()` / `nextPageUrl()` | Prev/next arrow hrefs |
| `linkCollection()` | Numbered page links (trimmed to exclude prev/next) |

Works identically with **[`Paginator`](https://laravel.com/api/12.x/Illuminate/Pagination/Paginator.html)** (for `simple` variant — no `total()` call) and **[`CursorPaginator`](https://laravel.com/api/12.x/Illuminate/Pagination/CursorPaginator.html)** (use `variant="mini"` — only `previousPageUrl`/`nextPageUrl` are needed).

## Accessibility

- The outer element is `<nav role="navigation" aria-label="Pagination">` — screen readers announce this as a navigation landmark
- The current page uses `aria-current="page"` per [WAI-ARIA Authoring Practices](https://www.w3.org/WAI/ARIA/apg/patterns/breadcrumb/)
- Prev/Next buttons have `aria-label="Previous"` / `aria-label="Next"` so their arrow glyphs are announced with meaning
- Disabled prev/next controls are rendered as `<span>` with `aria-hidden="true"` instead of `<a>` — they are not focusable and not announced as links
- Ellipses (`…`) are rendered with `aria-hidden="true"` (decorative)

## Keyboard Interaction

| Key | Action |
|-----|--------|
| `Tab` | Move focus through page links and prev/next buttons |
| `Enter` | Follow the focused link |

*Pagination renders as a list of native links and buttons — keyboard interaction is delegated to the browser.*

## Pitfalls

- **Don't drive pagination via `wire:click` events on each link.** The component renders native `<a>` elements pointing at real URLs (Laravel's `linkCollection()`); `wire:click` would intercept browser navigation and break the back button.
- **Don't show all 100 pages.** The component already truncates with ellipses (`…`) — overriding the truncation defeats accessibility (every link must fit in the keyboard tab order).
- **A cursor paginator always renders as `mini`, whatever you ask for.** `simple` and `full`
  state a page number or a total, and a `CursorPaginator` has neither by design — that is the
  point of cursor pagination, which exists for endless append-only lists that cannot afford a
  `COUNT(*)`. The component detects the shape and renders previous/next rather than failing,
  and says so in the log when `APP_DEBUG` is on. Pass `variant="mini"` to make the intent
  explicit and silence the note.

## Design Tokens

| Element | Token |
| --- | --- |
| Button background | `--color-wk-bg-elevated` |
| Button border | `--color-wk-border` |
| Button hover background | `--color-wk-bg-muted` |
| Button hover border | `--color-wk-border-hover` |
| Active page background | `--color-wk-accent` |
| Active page text | `--color-wk-accent-fg` |
| Disabled state | `--color-wk-bg-subtle` + `--opacity-wk-disabled` |
| Text color | `--color-wk-text` |
| Muted text (summary) | `--color-wk-text-muted` |
| Button radius | `--radius-wk-md` |
| Button height | `--size-wk-sm` |

## Customization

Override defaults without publishing views via `config/wirekit.php`:

```php
'components' => [
    'pagination' => [
        'variant' => 'simple',
    ],
],
```

## Usage & Conventions

> **Prop conventions** — this component uses one or more of the shared semantic prop names (`intent` / `variant` / `tone` / `surface`). See [Prop naming conventions](/extending/prop-naming-conventions) for the canonical vocabulary, alias matrix, and decision tree.

## Further Reading

- [Laravel: Pagination](https://laravel.com/docs/pagination)
- [Laravel: `LengthAwarePaginator`](https://laravel.com/api/12.x/Illuminate/Pagination/LengthAwarePaginator.html)
- [WAI-ARIA: `aria-current`](https://www.w3.org/TR/wai-aria-1.2/#aria-current)
