Back to catalog
Component detail entry
Navigation
@vean/ui
SPagination

Pagination

Pagination belongs to the Navigation category. Start with demos and usage, then use the API tables to finish integration and styling decisions.

Use the quick jump panel to reach overview, usage, demos, and API first, then continue through the full page.

Quick jump

Related components

If you are composing interactions in the same family, these components usually pair well together.

Pagination

Overview

Pagination is used for splitting up content or data into several pages, with a control for navigating to the next or previous page.

Features

  • Data-driven compact composition — SPagination delegates the whole structure to the Aria PaginationCompact, which owns the page windowing, default content, and internal composition (root → list → page items / actions → ellipsis).
  • Controlled or uncontrolled page state — page / pageSize support v-model (controlled), while defaultPage / defaultPageSize provide uncontrolled usage backed by useControllableState.
  • Smart page windowing — siblingCount controls how many page buttons surround the current page; showEdges: true always pins the first and last page and renders single or double ellipsis depending on where the current page sits.
  • Boundary auto-disable — prev/first are disabled on the first page and next/last on the last page; disabled: true disables the entire control and suppresses all interaction.
  • Four visual variants — variant (pure / solid / outline / soft), shape (rounded / square), and size (xs…2xl) are applied through the paginationVariants scv() recipe.
  • actionVariant — when enabled, the first/prev/next/last action buttons also take the current variant styling, which otherwise paints only the current page.
  • Eight customization slots — default (list), leading, trailing, first, prev, next, last, and ellipsis; dynamic slot forwarding keeps every Aria slot reachable from the styled wrapper.
  • Per-region props forwarding — listProps, listItemProps, ellipsisProps, firstProps, prevProps, nextProps, lastProps forward attributes to each region.
  • Full ARIA semantics — the root is a nav; the active page carries aria-current="page" and the selected state attribute; every button gets a localized aria-label.
  • Localized accessibility text — action labels and the page label template come from the locale registry (pageLabel supports the {value} placeholder) across 13 built-in languages.
  • RTL support — action icons are mirrored automatically via rtl:[&>svg]:rotate-180.
  • Aria composition — PaginationRoot / PaginationList / PaginationListItem / PaginationEllipsis / PaginationFirst / PaginationPrev / PaginationNext / PaginationLast are exported from @vean/aria/pagination for fully custom styled builds.

Usage

SPagination delegates its page windowing to Aria PaginationCompact. For unstyled, data-driven composition, import PaginationCompact from @vean/aria/pagination.

Demos

Basic

Slot

You can use the slot to customize the first, prev, next, and last buttons

Action

When actionVariant is true, the action button will use the variant styling

Show

When showFirstOrLast is false, the first and last buttons will not be shown

API

Aria Layer

11

Pagination

22 Props2 Emits7 Slots
Props
PropTypeDefaultDescription
class
ClassValue
—
Additional class names applied to the root element.
ui
Partial<PaginationUi>
—
The custom ui class names
size
ThemeSize
—
The size of the pagination
variant
PaginationVariant
—
The variant of the pagination
shape
PaginationShape
—
The shape of the pagination
actionVariant
boolean
—
Whether the first/prev/next/last action buttons also use the `variant` styling, which otherwise only paints the current page
showFirstOrLast
boolean
—
Whether to show a first or last.
listProps
PaginationListProps
—
Properties forwarded to the list element.
listItemProps
PaginationListItemProps
—
Properties forwarded to the list item element.
ellipsisProps
PaginationEllipsisProps
—
Properties forwarded to the ellipsis element.
firstProps
PaginationButtonProps
—
Properties forwarded to the first element.
prevProps
PaginationButtonProps
—
Properties forwarded to the prev element.
nextProps
PaginationButtonProps
—
Properties forwarded to the next element.
lastProps
PaginationButtonProps
—
Properties forwarded to the last element.
page
number
—
The controlled value of the current page. Can be bound as `v-model:page`.
defaultPage
number
—
The value of the page that should be active when initially rendered. Use when you do not need to control the value state.
pageSize
number
—
Number of items per page
defaultPageSize
number
10
The default value of `pageSize` when initially rendered. Use when you do not need to control the value state.
total
number
—
Number of items in your list
siblingCount
number
—
Number of sibling should be shown around the current page
disabled
boolean
—
When `true`, prevents the user from interacting with item
showEdges
boolean
—
When `true`, always show first page, last page, and ellipsis
Emits
Emit NameParametersDescription
update:page
number
Event handler called when the page value changes
update:pageSize
number
Event handler called when the page size value changes
Slots
Slot NameParametersDescription
leading
—
Custom content for the leading slot.
trailing
—
Custom content for the trailing slot.
first
—
Custom content for the first slot.
prev
—
Custom content for the prev slot.
next
—
Custom content for the next slot.
last
—
Custom content for the last slot.
ellipsis
—
Custom content for the ellipsis slot.

PaginationButton

4 Props
Props
PropTypeDefaultDescription
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
disabled
boolean
—
Whether the component is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

PaginationCompact

16 Props2 Emits7 Slots
Props
PropTypeDefaultDescription
showFirstOrLast
boolean
—
Whether to show a first or last.
listProps
PaginationListProps
—
Properties forwarded to the list element.
listItemProps
PaginationListItemProps
—
Properties forwarded to the list item element.
ellipsisProps
PaginationEllipsisProps
—
Properties forwarded to the ellipsis element.
firstProps
PaginationButtonProps
—
Properties forwarded to the first element.
prevProps
PaginationButtonProps
—
Properties forwarded to the prev element.
nextProps
PaginationButtonProps
—
Properties forwarded to the next element.
lastProps
PaginationButtonProps
—
Properties forwarded to the last element.
page
number
—
The controlled value of the current page. Can be bound as `v-model:page`.
defaultPage
number
—
The value of the page that should be active when initially rendered. Use when you do not need to control the value state.
pageSize
number
—
Number of items per page
defaultPageSize
number
10
The default value of `pageSize` when initially rendered. Use when you do not need to control the value state.
total
number
—
Number of items in your list
siblingCount
number
—
Number of sibling should be shown around the current page
disabled
boolean
—
When `true`, prevents the user from interacting with item
showEdges
boolean
—
When `true`, always show first page, last page, and ellipsis
Emits
Emit NameParametersDescription
update:page
number
Event handler called when the page value changes
update:pageSize
number
Event handler called when the page size value changes
Slots
Slot NameParametersDescription
leading
—
Custom content for the leading slot.
trailing
—
Custom content for the trailing slot.
first
—
Custom content for the first slot.
prev
—
Custom content for the prev slot.
next
—
Custom content for the next slot.
last
—
Custom content for the last slot.
ellipsis
—
Custom content for the ellipsis slot.

PaginationEllipsis

PaginationFirst

PaginationLast

PaginationList

PaginationListItem

5 Props
Props
PropTypeDefaultDescription
value
number
—
Value for the page
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
disabled
boolean
—
Whether the component is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

PaginationNext

PaginationPrev

PaginationRoot

8 Props2 Emits
Props
PropTypeDefaultDescription
page
number
—
The controlled value of the current page. Can be bound as `v-model:page`.
defaultPage
number
—
The value of the page that should be active when initially rendered. Use when you do not need to control the value state.
pageSize
number
—
Number of items per page
defaultPageSize
number
10
The default value of `pageSize` when initially rendered. Use when you do not need to control the value state.
total
number
—
Number of items in your list
siblingCount
number
—
Number of sibling should be shown around the current page
disabled
boolean
—
When `true`, prevents the user from interacting with item
showEdges
boolean
—
When `true`, always show first page, last page, and ellipsis
Emits
Emit NameParametersDescription
update:page
number
Event handler called when the page value changes
update:pageSize
number
Event handler called when the page size value changes

Notes

Architecture and benchmark comparison

ConcernSoybeanUIshadcn-vue PaginationAnt Design PaginationElement Plus Pagination
Aria / styled separation✅ @vean/aria/pagination + scv()❌ single package❌ single package❌ single package
Compact data-driven API✅ PaginationCompact + 8 typed slots✅ Pagination + PaginationItem parts✅ config-driven (total, current)✅ layout / components
Controlled / uncontrolled✅ page/defaultPage, pageSize/defaultPageSize✅ v-model✅ current / defaultCurrent✅ v-model
Ellipsis + pinned edges✅ showEdges + automatic single/double ellipsis✅ showEdges on PaginationItem✅ showLessItems / auto ellipsis✅ pager-count
Boundary auto-disable✅ prev/first at page 1, next/last at last page✅ disabled on parts✅ prevIcon/nextIcon handling✅ auto
Disable entire control✅ disabled✅✅ disabled✅ disabled
Selected page styling✅ data-[selected] + actionVariant✅ data-[active]✅ current item class✅ active
Localized aria-label✅ locale registry (13 langs, {value} interpolation)hard-coded / aria-label proppartial—
Variant system✅ pure/solid/outline/soft × rounded/square × xs…2xl✅ size only✅ size✅ small/default/large
Per-region props forwarding✅ 7 props groups✅ asChild per part✅ itemRender✅ per-part props
RTL icon mirroring✅ automatic—✅✅

Runtime considerations

  1. Window math — getRange shows both ellipsis only when the current page is far enough from both ends (leftSiblingIndex > firstPageIndex + 2 and rightSiblingIndex < lastPageIndex - 2); near either edge it degrades to a single ellipsis, otherwise the full range renders.
  2. total pages — pageCount is Math.max(1, Math.ceil(total / pageSize)), so an empty list still yields one page; a page above pageCount renders the last window without crashing.
  3. Controlled state sync — when bound with v-model:page, clicking an item emits update:page; the internal window follows the prop, so external page changes (e.g. after a fetch) re-render the correct window automatically.
  4. showFirstOrLast — setting it to false removes the first/last buttons but keeps prev/next; page count math is unaffected.
  5. actionVariant — it only lets the action buttons reuse the variant recipe; the selected page item always uses the data-[selected] styling regardless of this flag.
  6. Locale fallback — button labels come from useLocaleMessages; missing keys fall back to the default English bundle; pageLabel supports the {value} placeholder via interpolate.
  7. A11y output — the active page renders with aria-current="page" and the data-selected attribute; disabled actions keep disabled so they are skipped by assistive technology and keyboard navigation.

FAQ

When do the ellipsis appear?

With showEdges: true, the first and last page are always pinned. The current page sits at either edge of the window → one ellipsis; deep in the middle (e.g. page 50 of 100) → two ellipsis with siblingCount pages on each side. With showEdges: false, only the current window renders and no ellipsis is shown.

How do I make pagination controlled vs. uncontrolled?

Pass page (and optionally pageSize) together with an @update:page handler, or simply use v-model:page. For uncontrolled usage, rely on defaultPage / defaultPageSize and let the component manage its own state.

What is actionVariant for?

By default the first/prev/next/last action buttons use a neutral action style. When actionVariant is true, those buttons also take the variant styling — the same one the current page uses (e.g. a solid primary look) — which is useful when the active page visually merges with the action buttons.

Why are prev/first disabled on the first page?

The first/prev buttons disable automatically when page === 1 and next/last when page === pageCount, preventing out-of-range navigation. Set disabled: true to disable the whole control.

Can I fully customize the buttons?

Yes — the first, prev, next, last, ellipsis, leading, and trailing slots replace the default content, and firstProps / prevProps / nextProps / lastProps forward attributes (including styles) to the respective regions. The default list slot receives scoped { page, pageCount }-aware items through the Aria list.

How is accessibility handled?

The root is a nav landmark; every button carries a localized aria-label (the page buttons use the pageLabel template, e.g. “Page 5”); the active page is announced with aria-current="page"; disabled buttons use the native disabled attribute and are skipped by assistive technology.

Can I build a fully custom pagination?

Yes — compose PaginationRoot / PaginationList / PaginationListItem / PaginationEllipsis / PaginationFirst / PaginationPrev / PaginationNext / PaginationLast from @vean/aria/pagination and inject styles via providePaginationUi (or SPagination’s ui prop).

Changelog

Version history is grouped by release so you can quickly see what changed for this component across published versions.

v0.50.0

2026-10-02

Compare release

Breaking

rename actionAsSelected to actionVariant

Scope: paginationAuthors: soybeanjsView commit6eb3a

Docs

document the actionVariant rename in the v0.50.0 upgrade guide

Scope: paginationAuthors: soybeanjsView commitb7a29

Breaking

rename actionAsSelected to actionVariant

Scope: paginationAuthors: soybeanjsView commit6eb3a

Docs

document the actionVariant rename in the v0.50.0 upgrade guide

Scope: paginationAuthors: soybeanjsView commitb7a29

v0.20.0

2026-05-12

Compare release

Optimization

simplify Pagination component by using PaginationCompact

Scope: paginationAuthors: soybeanjsView commitfd3b9

v0.16.0

2026-05-01

Compare release

Feature

implement Compact components for Card, Popover, Editable, HoverCard, NavigationMenu, Pagination and Stepper

Scope: componentsAuthors: soybeanjsView commit6cbdc

v0.11.1

2026-03-06

Compare release

Feature

add leading and trailing slots

Scope: paginationAuthors: soybeanjsView commitb03ba

v0.11.0

2026-03-06

Compare release

Refactor

rename itemsPerPage to pageSize and support update pageSize by event

Scope: paginationAuthors: soybeanjsView commit7817c

v0.0.7

2025-12-09

Compare release

Fix

update border styles for selected button states in pagination variants

Scope: paginationAuthors: soybeanjsView commite817f

v0.0.2

2025-11-18

Compare release

Feature

implement pagination component with various features including action buttons, size, shape, and slot customization

Scope: paginationAuthors: soybeanjsView commitd2cf6

Feature

implement pagination component with various features including action buttons, size, shape, and slot customization

Scope: paginationAuthors: soybeanjsView commitd2cf6