Add this component

npx zentauri-ui add pagination

Accessibility notes

Keyboard accessible by default with semantic markup, visible focus treatment, and tokenized states. Add descriptive labels for icon-only or decorative usage.

Dependency notes

No extra runtime dependency beyond React and the package peers already covered in Installation.

Navigation

Pagination for large datasets

Pagination splits long datasets into navigable windows with clear current-page cues. Use it in React tables and Next.js routes that sync page index to the URL for shareable views.

Examples

Each block uses the same Show output / Show code toggle as the variant gallery below so you can match the live UI to a copy-ready snippet.


Controlled + compact

Middle window uses siblingCount; ends use boundaryCount. Prev and Next stay keyboard-friendly on the nav region.

Current page: 7


Headless API

Current page 7 of 40. canGoPrev=true, canGoNext=true.

[
  {
    "type": "page",
    "value": 1
  },
  {
    "type": "ellipsis",
    "key": "gap-1-6"
  },
  {
    "type": "page",
    "value": 6
  },
  {
    "type": "page",
    "value": 7
  },
  {
    "type": "page",
    "value": 8
  },
  {
    "type": "ellipsis",
    "key": "gap-8-40"
  },
  {
    "type": "page",
    "value": 40
  }
]

Pagination variants playground

Pick an appearance and size to preview the pagination live. Toggle Show output / Show code and the snippet updates to match the selected variant.


Appearance: DEFAULT, Size: MD

All appearances

Every shipped appearance token at a glance. Click any swatch to load it into the playground above.

default

secondary

destructive

outline

ghost

link

glass

emerald

indigo

purple

pink

rose

sky

teal

yellow

orange

gray

amber

violet

gradient-blue

gradient-green

gradient-red

gradient-yellow

gradient-purple

gradient-teal

gradient-indigo

gradient-pink

gradient-orange

blue

cyan

green

lime

mint

ocean

sapphire

lavender

ruby

red

slate

zinc

stone

royal

electric

forest

sunset

magenta

crimson

aqua

plum

Pagination API

Generated from the package prop types and variant definitions.

Pagination

PaginationProps

Variants

PropTypeDefault
size
10xl2xl3xl4xl5xl6xl7xl8xl9xliconlgmd+2
md

Behavior

PropTypeDefault
appearancePaginationAppearance | undefinednone
boundaryCountNumber of pages to keep visible at the start and end of the range.number | undefined1
defaultPagenumber | undefinednone
ellipsisLabelstring | undefinednone
getPageHrefWhen set, page controls render as anchors suitable for URL-based pagination.((page: number) => string | undefined) | undefinednone
nextLabelstring | undefinednone
onPageChange((page: number) => void) | undefinednone
pagenumber | undefinednone
pageCount*numbernone
prevLabelstring | undefinednone
showPrevNextboolean | undefinednone
siblingCountNumber of page buttons to show on each side of the current page (the “middle” window).number | undefined1
Inherited HTML props
PropTypeDefault
childrenReactNodenone
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone
CSS variable overrides

Pagination CSS variables

Override these pagination variables on :root, a theme selector, or a component wrapper.

302 variables

Pattern: --zui-<component>-<slot?>-<variant?>-<property>-<state?>-dark?

:root {
  --zui-pagination-list-ring-offset: oklch(98.4% 0.003 247.858);
  --zui-pagination-list-default-border: #0000001a;
  --zui-pagination-list-default-bg: #00000008;
  --zui-pagination-list-secondary-border: #0000001a;
  --zui-pagination-list-secondary-bg: oklch(96.8% 0.007 247.896 / 0.4);
  --zui-pagination-list-destructive-border: oklch(64.5% 0.246 16.439 / 0.25);
  --zui-pagination-list-destructive-bg: oklch(96.9% 0.015 12.422);
  --zui-pagination-list-outline-border: #00000026;
  --zui-pagination-list-outline-bg: transparent;
  --zui-pagination-list-ghost-border: transparent;
  --zui-pagination-list-ghost-bg: transparent;
  --zui-pagination-list-link-border: transparent;
  --zui-pagination-list-link-bg: transparent;
  --zui-pagination-list-glass-border: #00000026;
  --zui-pagination-list-glass-bg: #0000000d;
  --zui-pagination-list-emerald-border: oklch(69.6% 0.17 162.48 / 0.25);
  --zui-pagination-list-emerald-bg: oklch(97.9% 0.021 166.113);
  --zui-pagination-list-indigo-border: oklch(58.5% 0.233 277.117 / 0.25);
  --zui-pagination-list-indigo-bg: oklch(96.2% 0.018 272.314);
  --zui-pagination-list-purple-border: oklch(62.7% 0.265 303.9 / 0.25);
  --zui-pagination-list-purple-bg: oklch(97.7% 0.014 308.299);
  --zui-pagination-list-pink-border: oklch(65.6% 0.241 354.308 / 0.25);
  --zui-pagination-list-pink-bg: oklch(97.1% 0.014 343.198);
  --zui-pagination-list-rose-border: oklch(64.5% 0.246 16.439 / 0.25);
  --zui-pagination-list-rose-bg: oklch(96.9% 0.015 12.422);
  --zui-pagination-list-sky-border: oklch(68.5% 0.169 237.323 / 0.25);
  --zui-pagination-list-sky-bg: oklch(97.7% 0.013 236.62);
  --zui-pagination-list-teal-border: oklch(70.4% 0.14 182.503 / 0.25);
  --zui-pagination-list-teal-bg: oklch(98.4% 0.014 180.72);
  --zui-pagination-list-yellow-border: oklch(79.5% 0.184 86.047 / 0.25);
  --zui-pagination-list-yellow-bg: oklch(98.7% 0.026 102.212);
  --zui-pagination-list-orange-border: oklch(70.5% 0.213 47.604 / 0.25);
  --zui-pagination-list-orange-bg: oklch(98% 0.016 73.684);
  --zui-pagination-list-gray-border: oklch(55.1% 0.027 264.364 / 0.25);
  --zui-pagination-list-gray-bg: oklch(98.5% 0.002 247.839);
  --zui-pagination-list-amber-border: oklch(76.9% 0.188 70.08 / 0.25);
  --zui-pagination-list-amber-bg: oklch(98.7% 0.022 95.277);
  --zui-pagination-list-violet-border: oklch(60.6% 0.25 292.717 / 0.25);
  --zui-pagination-list-violet-bg: oklch(96.9% 0.016 293.756);
  --zui-pagination-list-gradient-blue-border: oklch(62.3% 0.214 259.815 / 0.3);
  --zui-pagination-list-gradient-blue-from: oklch(97% 0.014 254.604);
  --zui-pagination-list-gradient-blue-to: oklch(97.7% 0.014 308.299);
  --zui-pagination-list-gradient-green-border: oklch(76.8% 0.233 130.85 / 0.3);
  --zui-pagination-list-gradient-green-from: oklch(98.2% 0.018 155.826);
  --zui-pagination-list-gradient-green-to: oklch(98.6% 0.031 120.757);
  --zui-pagination-list-gradient-red-border: oklch(65.6% 0.241 354.308 / 0.3);
  --zui-pagination-list-gradient-red-from: oklch(97.1% 0.013 17.38);
  --zui-pagination-list-gradient-red-to: oklch(97.1% 0.014 343.198);
  --zui-pagination-list-gradient-yellow-border: oklch(70.5% 0.213 47.604 / 0.3);
  --zui-pagination-list-gradient-yellow-from: oklch(98.7% 0.026 102.212);
  --zui-pagination-list-gradient-yellow-to: oklch(98% 0.016 73.684);
  --zui-pagination-list-gradient-purple-border: oklch(65.6% 0.241 354.308 / 0.3);
  --zui-pagination-list-gradient-purple-from: oklch(97.7% 0.014 308.299);
  --zui-pagination-list-gradient-purple-to: oklch(97.1% 0.014 343.198);
  --zui-pagination-list-gradient-teal-border: oklch(71.5% 0.143 215.221 / 0.3);
  --zui-pagination-list-gradient-teal-from: oklch(98.4% 0.014 180.72);
  --zui-pagination-list-gradient-teal-to: oklch(98.4% 0.019 200.873);
  --zui-pagination-list-gradient-indigo-border: oklch(62.7% 0.265 303.9 / 0.3);
  --zui-pagination-list-gradient-indigo-from: oklch(96.2% 0.018 272.314);
  --zui-pagination-list-gradient-indigo-to: oklch(97.7% 0.014 308.299);
  --zui-pagination-list-gradient-pink-border: oklch(64.5% 0.246 16.439 / 0.3);
  --zui-pagination-list-gradient-pink-from: oklch(97.1% 0.014 343.198);
  --zui-pagination-list-gradient-pink-to: oklch(96.9% 0.015 12.422);
  --zui-pagination-list-gradient-orange-border: oklch(70.5% 0.213 47.604 / 0.3);
  --zui-pagination-list-gradient-orange-from: oklch(98% 0.016 73.684);
  --zui-pagination-list-gradient-orange-to: oklch(97.1% 0.013 17.38);
  --zui-pagination-list-blue-border: #2563eb;
  --zui-pagination-list-blue-bg: #2563eb14;
  --zui-pagination-list-blue-fg: #2563eb;
  --zui-pagination-list-blue-bg-hover: #2563eb18;
  --zui-pagination-list-cyan-border: #0891b2;
  --zui-pagination-list-cyan-bg: #0891b214;
  --zui-pagination-list-cyan-fg: #0891b2;
  --zui-pagination-list-cyan-bg-hover: #0891b218;
  --zui-pagination-list-green-border: #16a34a;
  --zui-pagination-list-green-bg: #16a34a14;
  --zui-pagination-list-green-fg: #16a34a;
  --zui-pagination-list-green-bg-hover: #16a34a18;
  --zui-pagination-list-lime-border: #65a30d;
  --zui-pagination-list-lime-bg: #65a30d14;
  --zui-pagination-list-lime-fg: #65a30d;
  --zui-pagination-list-lime-bg-hover: #65a30d18;
  --zui-pagination-list-mint-border: #10b981;
  --zui-pagination-list-mint-bg: #10b98114;
  --zui-pagination-list-mint-fg: #10b981;
  --zui-pagination-list-mint-bg-hover: #10b98118;
  --zui-pagination-list-ocean-border: #0284c7;
  --zui-pagination-list-ocean-bg: #0284c714;
  --zui-pagination-list-ocean-fg: #0284c7;
  --zui-pagination-list-ocean-bg-hover: #0284c718;
  --zui-pagination-list-sapphire-border: #1d4ed8;
  --zui-pagination-list-sapphire-bg: #1d4ed814;
  --zui-pagination-list-sapphire-fg: #1d4ed8;
  --zui-pagination-list-sapphire-bg-hover: #1d4ed818;
  --zui-pagination-list-lavender-border: #8b5cf6;
  --zui-pagination-list-lavender-bg: #8b5cf614;
  --zui-pagination-list-lavender-fg: #8b5cf6;
  --zui-pagination-list-lavender-bg-hover: #8b5cf618;
  --zui-pagination-list-ruby-border: #be123c;
  --zui-pagination-list-ruby-bg: #be123c14;
  --zui-pagination-list-ruby-fg: #be123c;
  --zui-pagination-list-ruby-bg-hover: #be123c18;
  --zui-pagination-list-red-border: #dc2626;
  --zui-pagination-list-red-bg: #dc262614;
  --zui-pagination-list-red-fg: #dc2626;
  --zui-pagination-list-red-bg-hover: #dc262618;
  --zui-pagination-list-slate-border: #475569;
  --zui-pagination-list-slate-bg: #47556914;
  --zui-pagination-list-slate-fg: #475569;
  --zui-pagination-list-slate-bg-hover: #47556918;
  --zui-pagination-list-zinc-border: #52525b;
  --zui-pagination-list-zinc-bg: #52525b14;
  --zui-pagination-list-zinc-fg: #52525b;
  --zui-pagination-list-zinc-bg-hover: #52525b18;
  --zui-pagination-list-stone-border: #57534e;
  --zui-pagination-list-stone-bg: #57534e14;
  --zui-pagination-list-stone-fg: #57534e;
  --zui-pagination-list-stone-bg-hover: #57534e18;
  --zui-pagination-list-royal-border: #4338ca;
  --zui-pagination-list-royal-bg: #4338ca14;
  --zui-pagination-list-royal-fg: #4338ca;
  --zui-pagination-list-royal-bg-hover: #4338ca18;
  --zui-pagination-list-electric-border: #0ea5e9;
  --zui-pagination-list-electric-bg: #0ea5e914;
  --zui-pagination-list-electric-fg: #0ea5e9;
  --zui-pagination-list-electric-bg-hover: #0ea5e918;
  --zui-pagination-list-forest-border: #166534;
  --zui-pagination-list-forest-bg: #16653414;
  --zui-pagination-list-forest-fg: #166534;
  --zui-pagination-list-forest-bg-hover: #16653418;
  --zui-pagination-list-sunset-border: #ea580c;
  --zui-pagination-list-sunset-bg: #ea580c14;
  --zui-pagination-list-sunset-fg: #ea580c;
  --zui-pagination-list-sunset-bg-hover: #ea580c18;
  --zui-pagination-list-magenta-border: #c026d3;
  --zui-pagination-list-magenta-bg: #c026d314;
  --zui-pagination-list-magenta-fg: #c026d3;
  --zui-pagination-list-magenta-bg-hover: #c026d318;
  --zui-pagination-list-crimson-border: #b91c1c;
  --zui-pagination-list-crimson-bg: #b91c1c14;
  --zui-pagination-list-crimson-fg: #b91c1c;
  --zui-pagination-list-crimson-bg-hover: #b91c1c18;
  --zui-pagination-list-aqua-border: #0f766e;
  --zui-pagination-list-aqua-bg: #0f766e14;
  --zui-pagination-list-aqua-fg: #0f766e;
  --zui-pagination-list-aqua-bg-hover: #0f766e18;
  --zui-pagination-list-plum-border: #7e22ce;
  --zui-pagination-list-plum-bg: #7e22ce14;
  --zui-pagination-list-plum-fg: #7e22ce;
  --zui-pagination-list-plum-bg-hover: #7e22ce18;
  --zui-pagination-ellipsis-fg: oklch(55.4% 0.046 257.417);
}

/* Dark theme variables follow the same names with -dark appended. */
.dark {
  --zui-pagination-list-ring-offset-dark: oklch(12.9% 0.042 264.695);
  --zui-pagination-list-default-border-dark: #ffffff1a;
}

What it does

Expose aria-current on the active page where applicable.

Keep page size controls near the pager when users frequently tune density.

Composition and API

Prefer compound subcomponents instead of one oversized prop bag. Export a small, documented API for your design system.

Ensure keyboard users can move across controls without excessive tab stops.

Common use cases

  • Server-rendered tables with querystring page params.
  • Admin audit logs with thousands of rows.
  • API-backed galleries with stable page sizes.
  • Embedded widgets inside dashboards.

Accessibility

Keyboard order, focus rings, and ARIA attributes should match production usage. Test with your supported browsers and assistive technologies when semantics are non-trivial.

This preview page exposes a single h1 in the hero for a clean outline.

Next.js integration notes

Colocate examples under the App Router, keep server and client boundaries explicit, and avoid pulling interactive overlays into unexpected server layouts.

Set NEXT_PUBLIC_SITE_URL so canonical and Open Graph URLs resolve on deploy.

FAQ

Does the Pagination component work with Next.js App Router?

Yes. Import it like any other React component; keep interactive subtrees in client components when you need hooks or browser APIs, and leave static structure in server components where possible.

Can I customize pagination with Tailwind CSS?

Zentauri UI exposes class-friendly variants and slots so you can extend styles with Tailwind utilities without fighting inline styles.

Is this Pagination implementation accessible by default?

Primitives follow sensible defaults, but accessibility depends on how you label controls, manage focus, and wire keyboard handlers in your app. Validate critical flows with keyboard-only use and screen readers.