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

PropDefaultDescription
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.
currentfalseHighlights the page as the active page with indigo background.
disabledfalseDisables 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"
    >
      &hellip;
    </span>
  );
}

export {
  Pagination,
  PaginationPrevious,
  PaginationNext,
  PaginationList,
  PaginationPage,
  PaginationGap,
};
export default Pagination;