Pagination
Page navigation controls with numbered pages, previous/next buttons, ellipsis gaps, active page indicator, and disabled state support.
Preview
Basic pagination
import { Pagination, PaginationPrevious, PaginationNext, PaginationList, PaginationPage } from '@/registry/ui-kit/tailwind-pagination/react'
function Example() {
return (
<Pagination>
<PaginationPrevious href="#" />
<PaginationList>
<PaginationPage href="#">1</PaginationPage>
<PaginationPage href="#">2</PaginationPage>
<PaginationPage current href="#">3</PaginationPage>
<PaginationPage href="#">4</PaginationPage>
<PaginationPage href="#">5</PaginationPage>
</PaginationList>
<PaginationNext href="#" />
</Pagination>
)
}With gap
import { Pagination, PaginationPrevious, PaginationNext, PaginationList, PaginationPage, PaginationGap } from '@/registry/ui-kit/tailwind-pagination/react'
function Example() {
return (
<Pagination>
<PaginationPrevious href="#" />
<PaginationList>
<PaginationPage href="#">1</PaginationPage>
<PaginationPage current href="#">2</PaginationPage>
<PaginationPage href="#">3</PaginationPage>
<PaginationGap />
<PaginationPage href="#">10</PaginationPage>
</PaginationList>
<PaginationNext href="#" />
</Pagination>
)
}Disabled navigation
import { Pagination, PaginationPrevious, PaginationNext, PaginationList, PaginationPage } from '@/registry/ui-kit/tailwind-pagination/react'
function Example() {
return (
<Pagination>
<PaginationPrevious disabled />
<PaginationList>
<PaginationPage current href="#">1</PaginationPage>
<PaginationPage href="#">2</PaginationPage>
<PaginationPage href="#">3</PaginationPage>
</PaginationList>
<PaginationNext disabled />
</Pagination>
)
}Component API
| Prop | Default | Description |
|---|---|---|
Pagination | — | Wrapper nav element with flex layout. |
PaginationPrevious | — | Previous page button with left arrow SVG. Accepts disabled prop. |
PaginationNext | — | Next page button with right arrow SVG. Accepts disabled prop. |
PaginationList | — | Container for page number buttons. |
PaginationPage | — | Page number link. Accepts current boolean and href. |
current | false | Highlights the page as the active page with indigo background. |
disabled | false | Disables prev/next buttons with reduced opacity. |
PaginationGap | — | Renders an ellipsis to indicate skipped pages. |
Source Code
"use client";
/* ── Base button styles ── */
const baseStyles =
"inline-flex h-9 min-w-9 items-center justify-center rounded-lg px-3 text-sm font-medium transition-colors";
const currentStyles = "bg-indigo-600 text-white";
const defaultStyles =
"text-zinc-500 hover:bg-zinc-100 dark:text-zinc-400 dark:hover:bg-zinc-800";
const disabledStyles = "opacity-50 cursor-not-allowed";
/* ── Pagination ── */
interface PaginationProps {
children: React.ReactNode;
className?: string;
}
function Pagination({ children, className = "" }: PaginationProps) {
return (
<nav
aria-label="Pagination"
className={`flex items-center gap-1 ${className}`}
>
{children}
</nav>
);
}
/* ── PaginationPrevious ── */
interface PaginationPreviousProps
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
disabled?: boolean;
className?: string;
}
function PaginationPrevious({
disabled = false,
className = "",
...props
}: PaginationPreviousProps) {
const Tag = disabled ? "span" : "a";
return (
<Tag
className={`${baseStyles} ${disabled ? disabledStyles : defaultStyles} ${className}`}
aria-label="Previous page"
aria-disabled={disabled || undefined}
{...(disabled ? {} : props)}
>
<svg
className="h-4 w-4"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="m15 18-6-6 6-6" />
</svg>
</Tag>
);
}
/* ── PaginationNext ── */
interface PaginationNextProps
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
disabled?: boolean;
className?: string;
}
function PaginationNext({
disabled = false,
className = "",
...props
}: PaginationNextProps) {
const Tag = disabled ? "span" : "a";
return (
<Tag
className={`${baseStyles} ${disabled ? disabledStyles : defaultStyles} ${className}`}
aria-label="Next page"
aria-disabled={disabled || undefined}
{...(disabled ? {} : props)}
>
<svg
className="h-4 w-4"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="m9 18 6-6-6-6" />
</svg>
</Tag>
);
}
/* ── PaginationList ── */
interface PaginationListProps {
children: React.ReactNode;
className?: string;
}
function PaginationList({ children, className = "" }: PaginationListProps) {
return (
<span className={`flex items-center gap-1 ${className}`}>{children}</span>
);
}
/* ── PaginationPage ── */
interface PaginationPageProps
extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
current?: boolean;
className?: string;
children: React.ReactNode;
}
function PaginationPage({
current = false,
children,
className = "",
...props
}: PaginationPageProps) {
return (
<a
className={`${baseStyles} ${current ? currentStyles : defaultStyles} ${className}`}
aria-current={current ? "page" : undefined}
{...props}
>
{children}
</a>
);
}
/* ── PaginationGap ── */
interface PaginationGapProps {
className?: string;
}
function PaginationGap({ className = "" }: PaginationGapProps) {
return (
<span
className={`${baseStyles} text-zinc-400 dark:text-zinc-500 ${className}`}
aria-hidden="true"
>
…
</span>
);
}
export {
Pagination,
PaginationPrevious,
PaginationNext,
PaginationList,
PaginationPage,
PaginationGap,
};
export default Pagination;