Pagination

Page navigation in the seam grouped-control language: links sit in a debossed well and the current page rises as an embossed key, springing to whichever page you pick.

Click a page — the embossed key springs to it (an instant jump under reduced motion).

tsx
"use client"

import * as React from "react"

import {
  Pagination,
  PaginationContent,
  PaginationEllipsis,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/registry/seam/ui/pagination"

// Controlled pagination: the embossed key springs to the page you pick.
export default function PaginationDemo() {
  const [page, setPage] = React.useState(2)
  const last = 12

  const go = (p: number) => (e: React.MouseEvent) => {
    e.preventDefault()
    setPage(p)
  }

  return (
    <Pagination>
      <PaginationContent>
        <PaginationItem>
          <PaginationPrevious
            href="#"
            disabled={page === 1}
            onClick={go(page - 1)}
          />
        </PaginationItem>
        {[1, 2, 3].map((p) => (
          <PaginationItem key={p}>
            <PaginationLink href="#" isActive={p === page} onClick={go(p)}>
              {p}
            </PaginationLink>
          </PaginationItem>
        ))}
        <PaginationItem>
          <PaginationEllipsis />
        </PaginationItem>
        <PaginationItem>
          <PaginationLink href="#" isActive={page === last} onClick={go(last)}>
            {last}
          </PaginationLink>
        </PaginationItem>
        <PaginationItem>
          <PaginationNext
            href="#"
            disabled={page === last}
            onClick={go(page === last ? page : page + 1)}
          />
        </PaginationItem>
      </PaginationContent>
    </Pagination>
  )
}
bunx --bun @seamui/cli@latest add pagination

API

PropTypeDefaultDescription
isActivebooleanOn PaginationLink — the current page: embossed key, aria-current="page".
disabledbooleanOn any link — non-navigable prev/next at the range ends (aria-disabled, unfocusable).
size"icon" | "default""icon"On PaginationLink — square page key, or a wide key for labelled prev/next.

Links are plain <a> elements — pass href for real navigation or onClick for controlled state.

Notes

  • The tabs/toggle-group idea again: a debossed well (shadow-well) holds the keys and the active page is embossed (shadow-resting), springing between links via a shared layout animation — a static jump under reduced motion.
  • Page keys are links, not buttons — they wear buttonVariants directly so the pagination nav keeps real link semantics (aria-current, native navigation).
  • Committing a page change fires the tick haptic; re-clicking the active page doesn't.
  • For table pagination wired to TanStack state, Data Table ships its own footer — this component is for page-level navigation.

Press feedback, reduced motion, and haptics follow the global policy — see Motion and Haptics.