Navigation
Pagination code
Copy the implementation or inspect every file that belongs to this component unit.
resources/views/components/ui/pagination.blade.php
@props([
'paginator' => null,
'currentPage' => 1,
'lastPage' => 1,
'onEachSide' => 1,
'ajax' => false,
'variant' => 'full',
])
@php
/*
| Page navigation. Pass a Laravel `paginator` (LengthAwarePaginator) and it
| wires up the links automatically, or pass `currentPage` / `lastPage` plus a
| `href` callback via the `links` slot for manual control.
|
| variant: full (numbered window) or simple (prev/next with "Page X of Y").
| A CursorPaginator automatically renders as simple prev/next.
|
| Usage:
| <x-ui.pagination :paginator="$users" />
| <x-ui.pagination :current-page="3" :last-page="10" />
| <x-ui.pagination variant="simple" :current-page="3" :last-page="10" />
| <x-ui.pagination :paginator="$users->cursorPaginate(15)" />
*/
use Illuminate\Contracts\Pagination\CursorPaginator as CursorPaginatorContract;
$isCursor = $paginator instanceof CursorPaginatorContract;
if ($isCursor) {
$variant = 'simple';
$prevUrl = $paginator->previousPageUrl();
$nextUrl = $paginator->nextPageUrl();
$currentPage = null;
$lastPage = null;
} else {
if ($paginator) {
$currentPage = $paginator->currentPage();
$lastPage = $paginator->lastPage();
}
$currentPage = (int) $currentPage;
$lastPage = (int) $lastPage;
$prevUrl = $currentPage > 1 ? ($paginator ? $paginator->url($currentPage - 1) : '#') : '#';
$nextUrl = $currentPage < $lastPage ? ($paginator ? $paginator->url($currentPage + 1) : '#') : '#';
}
// Build a compact window of page numbers with ellipsis gaps.
$window = [];
if (! $isCursor && $variant === 'full') {
if ($lastPage <= 7 + ($onEachSide * 2)) {
$window = range(1, max(1, $lastPage));
} else {
$window[] = 1;
$start = max(2, $currentPage - $onEachSide);
$end = min($lastPage - 1, $currentPage + $onEachSide);
if ($start > 2) { $window[] = '...'; }
for ($i = $start; $i <= $end; $i++) { $window[] = $i; }
if ($end < $lastPage - 1) { $window[] = '...'; }
$window[] = $lastPage;
}
}
$hasPrev = $isCursor ? filled($prevUrl) : $currentPage > 1;
$hasNext = $isCursor ? filled($nextUrl) : $currentPage < $lastPage;
$linkBase = 'inline-flex items-center justify-center min-w-9 h-9 px-2 rounded-lg text-sm font-medium transition-[box-shadow,color]';
$idle = 'text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800';
$active = 'bg-brand-600 text-white';
$disabled = 'text-gray-300 dark:text-gray-600 pointer-events-none';
@endphp
<nav
role="navigation"
aria-label="Pagination"
@if ($ajax) data-ajax-pagination @endif
{{ $attributes->merge(['class' => 'flex items-center justify-between gap-2']) }}
>
@if ($variant === 'simple')
<a href="{{ $hasPrev ? $prevUrl : '#' }}"
class="{{ $linkBase }} px-3 {{ $hasPrev ? $idle : $disabled }}"
@if (! $hasPrev) aria-disabled="true" @endif>
<x-ui.icon name="arrow-left" weight="bold" size="sm" class="me-1" /> Previous
</a>
@if (! $isCursor)
<span class="text-sm text-gray-500 dark:text-gray-400">
Page <span class="font-semibold text-gray-900 dark:text-white">{{ $currentPage }}</span> of {{ $lastPage }}
</span>
@endif
<a href="{{ $hasNext ? $nextUrl : '#' }}"
class="{{ $linkBase }} px-3 {{ $hasNext ? $idle : $disabled }}"
@if (! $hasNext) aria-disabled="true" @endif>
Next <x-ui.icon name="arrow-right" weight="bold" size="sm" class="ms-1" />
</a>
@else
{{-- Mobile: prev / next --}}
<div class="flex flex-1 items-center justify-between sm:hidden">
<a href="{{ $hasPrev ? $prevUrl : '#' }}"
class="{{ $linkBase }} px-3 {{ $hasPrev ? $idle : $disabled }}"
@if (! $hasPrev) aria-disabled="true" @endif>
<x-ui.icon name="arrow-left" weight="bold" size="sm" class="me-1" /> Previous
</a>
<a href="{{ $hasNext ? $nextUrl : '#' }}"
class="{{ $linkBase }} px-3 {{ $hasNext ? $idle : $disabled }}"
@if (! $hasNext) aria-disabled="true" @endif>
Next <x-ui.icon name="arrow-right" weight="bold" size="sm" class="ms-1" />
</a>
</div>
{{-- Desktop: full range --}}
<div class="hidden w-full items-center justify-center gap-1 sm:flex">
<a href="{{ $hasPrev ? $prevUrl : '#' }}"
class="{{ $linkBase }} {{ $hasPrev ? $idle : $disabled }}"
aria-label="Previous page" @if (! $hasPrev) aria-disabled="true" @endif>
<x-ui.icon name="caret-left" weight="bold" size="sm" />
</a>
@foreach ($window as $page)
@if ($page === '...')
<span class="inline-flex h-9 min-w-9 items-center justify-center text-sm text-gray-400 dark:text-gray-500">…</span>
@else
<a href="{{ $paginator ? $paginator->url($page) : '#' }}"
class="{{ $linkBase }} {{ $page === $currentPage ? $active : $idle }}"
@if ($page === $currentPage) aria-current="page" @endif>{{ $page }}</a>
@endif
@endforeach
<a href="{{ $hasNext ? $nextUrl : '#' }}"
class="{{ $linkBase }} {{ $hasNext ? $idle : $disabled }}"
aria-label="Next page" @if (! $hasNext) aria-disabled="true" @endif>
<x-ui.icon name="caret-right" weight="bold" size="sm" />
</a>
</div>
@endif
</nav>