Pagination
Page links with previous and next controls for moving through a long list.
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationLink,
PaginationPrevious,
PaginationNext,
PaginationEllipsis,
} from '@/components/ui/pagination'
export default function PaginationDemo() {
return (
<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationPrevious href="#" />
</PaginationItem>
<PaginationItem>
<PaginationLink href="#">1</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="#" isActive>
2
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="#">3</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationEllipsis />
</PaginationItem>
<PaginationItem>
<PaginationLink href="#">10</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationNext href="#" />
</PaginationItem>
</PaginationContent>
</Pagination>
)
}
Installation
pnpm dlx shadcn@latest add https://kagadmodyaa.vercel.app/r/pagination.jsonNeeds a React + Tailwind project set up with shadcn. Copies the component source straight into your project, so you can edit it.
Pagination imports cn() from lib/utils.ts — add it too if you don't have it yet:
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Its links are styled with buttonVariants. The CLI installs Button for you; if you copy manually, add components/ui/button.tsx too.
Usage
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationLink,
PaginationPrevious,
PaginationNext,
PaginationEllipsis,
} from '@/components/ui/pagination'
<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationPrevious href="?page=1" />
</PaginationItem>
<PaginationItem>
<PaginationLink href="?page=1">1</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="?page=2" isActive>2</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationEllipsis />
</PaginationItem>
<PaginationItem>
<PaginationNext href="?page=3" />
</PaginationItem>
</PaginationContent>
</Pagination>Examples
Interactive
'use client'
import * as React from 'react'
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationLink,
PaginationPrevious,
PaginationNext,
PaginationEllipsis,
} from '@/components/ui/pagination'
const TOTAL = 12
/** The pages to show: the first, the last, and a window around the current one — with gaps as null. */
function visiblePages(current: number, total: number): (number | null)[] {
const pages = new Set([1, total, current - 1, current, current + 1])
const sorted = [...pages].filter(p => p >= 1 && p <= total).sort((a, b) => a - b)
const out: (number | null)[] = []
sorted.forEach((page, i) => {
if (i > 0 && page - sorted[i - 1] > 1) out.push(null)
out.push(page)
})
return out
}
export default function PaginationInteractive() {
const [page, setPage] = React.useState(6)
const go = (next: number) => (event: React.MouseEvent) => {
event.preventDefault()
setPage(Math.min(TOTAL, Math.max(1, next)))
}
return (
<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationPrevious href="#" onClick={go(page - 1)} aria-disabled={page === 1} className={page === 1 ? 'pointer-events-none opacity-50' : undefined} />
</PaginationItem>
{visiblePages(page, TOTAL).map((p, i) =>
p === null ? (
<PaginationItem key={`gap-${i}`}>
<PaginationEllipsis />
</PaginationItem>
) : (
<PaginationItem key={p}>
<PaginationLink href="#" isActive={p === page} onClick={go(p)}>
{p}
</PaginationLink>
</PaginationItem>
),
)}
<PaginationItem>
<PaginationNext href="#" onClick={go(page + 1)} aria-disabled={page === TOTAL} className={page === TOTAL ? 'pointer-events-none opacity-50' : undefined} />
</PaginationItem>
</PaginationContent>
</Pagination>
)
}
API Reference
| Name | Type | Default | Description |
|---|---|---|---|
| Pagination | <nav> | — | The navigation landmark, labelled "pagination". |
| PaginationLink isActive | boolean | false | Marks the current page: outlined, and announced with aria-current="page". |
| PaginationLink size | 'sm' | 'default' | 'lg' | 'icon' | 'icon' | Button size of the link. |
| PaginationPrevious / PaginationNext | <a> | — | Links with a chevron and a label that hides on small screens. Pass children to replace the label. |
| PaginationEllipsis | <span> | — | A gap in the page numbers. Decorative, hidden from assistive technology. |