Zetta v1.6

Components · Wayfinding

Pagination

A row of page-number and previous/next controls. The current page takes the Primary fill; prev/next disable at the bounds. Every item is at least a 32×32 target.

Preview

Build with the skill

No package to install — hand this to your AI to generate or migrate the component in your stack.

Prompt for your AI
Apply the Zetta "Pagination" component to this project using the zetta-design-md skill.

WHEN TO USE
- Migrating or fixing existing code (the common case): audit the current implementation against the `pagination` spec (variants: item, active, disabled) and CORRECT every deviation — replace off-spec values, don't only add new ones.
- New component: build it to the `pagination` spec in this project's stack.

AUDIT & FIX (when the component already exists)
Compare it to the skill's spec and fix, don't just append: hardcoded colors/hex, off-scale radius, wrong fonts, dark/navy fills, shadows used in place of borders (or missing borders), brand lime used as a CTA or interaction (must be primary indigo), and any missing or wrong hover / focus / active / disabled / invalid state or missing 2px focus ring. Replace each with the correct Zetta token.

ALWAYS
- Pull the authoritative spec and tokens from the skill — never guess or hardcode values.
- Use this project's own component conventions and framework idioms.
- Honor the Zetta guardrails (brand = identity only, primary = interaction, shadows for overlays) and verify in Light, Dark, and Accessibility.

Anatomy & rules

← nav aria-label="Pagination" ─────────────────────────────────────
1–25 of 340            [← Prev]  [1] [2] [3] […] [14]  [Next →]
↑ pagination-info                 ↑ active    ↑ ellipsis
                                                         Show: [25 ▾]
                                                         ↑ pagination-page-size
State Visual
Default Page numbers, prev/next arrows
Current page {colors.primary} fill, {colors.primary-text} number
Page hover {colors.surface-muted} fill
Page focus 2px solid {colors.border-focus} outline
Prev/Next disabled {colors.disabled-text}, not-allowed cursor
Loading Skeleton for page numbers

When to use

  • Tables, lists, and grids with more rows than pageSize allows on one screen.
  • Server-side paginated data where loading all records at once is impractical.

When not to use

  • Lists under 25 items — show all items instead.
  • Infinite scroll patterns — pagination and infinite scroll are mutually exclusive.

Do

  • Show the page range info ("1–25 of 340") — users need to know the dataset size.
  • Offer a page-size selector when the dataset is large and users vary in how many items they want to scan at once.
  • Keep Previous/Next labels visible alongside the arrow icon — don't use icon only.

Don't

  • Don't use pagination inside a modal or popover.
  • Don't reset to page 1 automatically unless the user changes the search query or applies a new filter.
  • "Previous" and "Next" — always spelled out, not abbreviated.
  • Page range: "1–25 of 340" — use en-dash (–) not hyphen.
  • Page size label: "Show: [25 ▾]" or "Rows per page: [25 ▾]".

Keyboard

Key Behavior
Tab Move focus through pagination controls
Enter / Space Navigate to the focused page
Left / Right Arrow Move focus between page items

Accessibility

  • Wrap in <nav aria-label="Pagination">.
  • Active page button: aria-current="page".
  • Disabled Prev/Next: aria-disabled="true" — keep in tab order so screen readers can announce they are unavailable.
  • Ellipsis: aria-hidden="true" — it is decorative, not interactive.
  • Each page button: aria-label="Page 3" (not just the number).

Spec

Values and token references resolved straight from the Zetta spec.

pagination-item
backgroundColor
{colors.surface-card}
textColor
{colors.ink}
borderColor
{colors.border-strong}
borderWidth
1px
borderRadius
{rounded.base}
fontFamily
Geist
fontSize
14px
fontWeight
500
height
32px
minWidth
32px
paddingX
12px
display
flex
alignItems
center
justifyContent
center
cursor
pointer
pagination-item-hover
backgroundColor
{colors.primary-bg}
textColor
{colors.primary}
pagination-item-focus
outline
2px solid {colors.border-focus}
outlineOffset
2px
pagination-item-active
backgroundColor
{colors.primary}
textColor
{colors.primary-text}
borderColor
{colors.primary}
pagination-item-disabled
backgroundColor
{colors.disabled-bg}
textColor
{colors.disabled-text}
borderColor
{colors.disabled-border}
cursor
not-allowed
pagination-prev-next
display
flex
alignItems
center
gap
{spacing.xs}
iconSize
{icons.sizeMap.md}
pagination-ellipsis
height
32px
minWidth
32px
display
flex
alignItems
center
justifyContent
center
textColor
{colors.muted}
fontFamily
Geist
fontSize
14px
cursor
default
userSelect
none
pagination-list
display
flex
alignItems
center
gap
{spacing.xs}
pagination-info
fontFamily
Geist
fontSize
13px
fontWeight
400
textColor
{colors.muted}
pagination-page-size
display
flex
alignItems
center
gap
{spacing.sm}
fontFamily
Geist
fontSize
13px
textColor
{colors.muted}

Known gaps

  • Compact pagination variant (Previous / Next only, no numbered list) — not yet specified.
  • Mobile truncation behavior (show only Prev / current / Next on narrow viewports) — not yet specified.