import { Pagination, PaginationItem, PaginationListItem } from '@vega-ui/react';
<nav aria-label='Pagination'>
<Pagination>
{[1, 2, 3, 4].map((page) => (
<PaginationListItem key={page}>
<PaginationItem current={page === 2}>{page}</PaginationItem>
</PaginationListItem>
))}
</Pagination>
</nav>- Browser support
- Newly available 2024
- Chrome 125
- Edge 125
- Firefox 128
- Safari 18
- Safari on iOS 18
- Bundle size
Summary
Pagination is a compound component for paged navigation. It coordinates page items, trigger buttons, ellipsis placeholders, and optional supporting text while leaving the canonical page state in the parent feature.
Imports
import {
Pagination,
PaginationEllipsis,
PaginationItem,
PaginationListItem,
PaginationText,
PaginationTriggerIconButton,
type PaginationEllipsisProps,
type PaginationItemProps,
type PaginationListItemProps,
type PaginationProps,
type PaginationSize,
type PaginationTextProps,
type PaginationTriggerIconButtonProps,
type PaginationVariant,
} from '@vega-ui/react';Exported Types
PaginationPropsPaginationItemPropsPaginationTriggerIconButtonPropsPaginationEllipsisPropsPaginationListItemPropsPaginationTextPropsPaginationSizePaginationVariant
Minimal Composition
Pagination renders a plain <ul> and keeps no page state: the parent owns the current page, and a <nav> with its own aria-label gives the list a landmark. Wrap every item and trigger in PaginationListItem, but not PaginationText, which already renders its own <li>. Icon-only triggers need an icon child and an aria-label.
import { ChevronLeft, ChevronRight } from '@vega-ui/icons';
import {
Icon,
Pagination,
PaginationItem,
PaginationListItem,
PaginationTriggerIconButton,
} from '@vega-ui/react';
import { useState } from 'react';
export default function MinimalComposition() {
const [page, setPage] = useState(1);Required Parts
Pagination: root context and list containerPaginationListItem: list wrapper for each visible item- one of
PaginationItem,PaginationTriggerIconButton,PaginationEllipsis, orPaginationText
Optional Parts
PaginationText: compact textual summary such asPage 3 of 20PaginationEllipsis: gap indicator for truncated page ranges
Composition Order
Pagination- repeated
PaginationListItem - inside each item, one pagination child part
Variants
- Size: inherited from button/icon-button sizing
- Variant:
primaryorsecondary - Interaction model: link-based or button-based pagination
Edge Cases
- First and last page behavior should be explicit.
- The pagination UI should not become the source of truth for data state.
- Ellipsis should preserve current-page context rather than hiding it entirely.
Common Mistakes
- Forgetting disabled behavior at page boundaries.
- Treating pagination visuals as the only state model.
- Using pagination when infinite scroll or filtering is a better fit for the data.
Examples
Basic
Basic: page window with ellipses
The parent keeps the current page in state and computes which pages to show with getPageItems(page, total, siblings): always the first and last page, the current page with one sibling on each side, and an ellipsis wherever at least two pages are hidden. Previous and next are disabled at the boundaries.
import { ChevronLeft, ChevronRight } from '@vega-ui/icons';
import {
Icon,
Pagination,
PaginationEllipsis,
PaginationItem,
PaginationListItem,
PaginationTriggerIconButton,
} from '@vega-ui/react';
import { useState } from 'react';
type PageItem = number | 'start-ellipsis' | 'end-ellipsis';Basic: links with real hrefs
Every page is a real <a href='?page=N'> rendered through asChild, so pages can be opened in a new tab, shared and crawled. The current page is read from the URL after mount and marked with aria-current='page'; at the boundaries the previous or next link loses its href and gets aria-disabled.
import { ChevronLeft, ChevronRight } from '@vega-ui/icons';
import {
Icon,
Pagination,
PaginationEllipsis,
PaginationItem,
PaginationListItem,
PaginationTriggerIconButton,
} from '@vega-ui/react';
import { useEffect, useState } from 'react';
type PageItem = number | 'start-ellipsis' | 'end-ellipsis';Controlled/Stateful
Controlled/Stateful: paging through a table
The page number slices a list of 47 orders into pages of 10. The summary next to the controls (“Showing 11–20 of 47 orders”) is derived from the same state and announced politely when the page changes.
import { ChevronLeft, ChevronRight } from '@vega-ui/icons';
import {
Icon,
Pagination,
PaginationItem,
PaginationListItem,
PaginationTriggerIconButton,
Table,
TableBody,
TableData,
TableHead,
TableHeading,Form/Integration
Form/Integration: go to a page
A small form next to the pagination jumps straight to a page among 48. The number input has min, max and required, so the browser rejects out-of-range values before submit; the handler reads the value with FormData and resets the field.
import { ChevronLeft, ChevronRight } from '@vega-ui/icons';
import {
Button,
Icon,
Label,
Pagination,
PaginationEllipsis,
PaginationItem,
PaginationListItem,
PaginationTriggerIconButton,
TextField,
TextFieldInput,Layout/Overlay
Layout/Overlay: compact controls in a table footer
In a dense table footer the page numbers give way to a PaginationText range (“6–10 of 23”) and two icon triggers. PaginationText renders its own list item, so it sits directly inside Pagination.
import { ChevronLeft, ChevronRight } from '@vega-ui/icons';
import {
Icon,
Pagination,
PaginationListItem,
PaginationText,
PaginationTriggerIconButton,
Table,
TableBody,
TableData,
TableFoot,
TableHead,Error
Error: current page disappears after filtering
The requested page lives in state separately from the page that is actually shown. When a filter leaves fewer pages than requested, the example shows the last existing page and an error HelperText linked to the navigation; clearing the filter brings the requested page back and removes the message.
import { ChevronLeft, ChevronRight } from '@vega-ui/icons';
import {
HelperText,
Icon,
Label,
Pagination,
PaginationItem,
PaginationListItem,
PaginationTriggerIconButton,
Text,
TextField,
TextFieldInput,Disabled
Disabled: locked while a page loads
While the next page is loading, a native <fieldset disabled> disables every page button and trigger at once, so the user cannot queue several requests. The status line below says which page is loading.
import { ChevronLeft, ChevronRight } from '@vega-ui/icons';
import {
Icon,
Pagination,
PaginationItem,
PaginationListItem,
PaginationTriggerIconButton,
Spinner,
Text,
} from '@vega-ui/react';
import { useEffect, useState } from 'react';
Edge
Edge: very large ranges
The same window algorithm with first and last triggers on 7, 20 and 1000 pages and 0–2 siblings. The number of items stays constant while you move, so the controls do not jump; with few pages every page is shown and no ellipsis appears.
import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from '@vega-ui/icons';
import {
Button,
Icon,
Pagination,
PaginationEllipsis,
PaginationItem,
PaginationListItem,
PaginationTriggerIconButton,
Text,
} from '@vega-ui/react';
import { useState } from 'react';Edge: right-to-left layout and Arabic numerals
Inside dir='rtl' the flex row reverses on its own, but the arrow icons do not: “previous” points right and “next” points left. Page numbers and their labels are formatted with Intl.NumberFormat('ar-EG').
import { ChevronLeft, ChevronRight } from '@vega-ui/icons';
import {
Icon,
Pagination,
PaginationEllipsis,
PaginationItem,
PaginationListItem,
PaginationTriggerIconButton,
} from '@vega-ui/react';
import { useState } from 'react';
type PageItem = number | 'start-ellipsis' | 'end-ellipsis';Anatomy
Overview
Pagination is a compositional navigation system. The root shares size and variant context, while each list item wraps one visible pagination affordance.
Required Parts
Pagination
Required. Owns shared size and variant context and renders the outer list.
PaginationListItem
Required in normal composition. Preserves list semantics for each visible pagination element.
PaginationItem or PaginationTriggerIconButton
Normally required. These are the main interactive page affordances.
Optional Parts
PaginationEllipsis
Optional. Indicates truncated ranges.
PaginationText
Optional. Shows compact textual pagination status.
Composition Order
Pagination- repeated
PaginationListItem - one child part per list item
Valid Composition Patterns
import { ChevronLeft, ChevronRight } from '@vega-ui/icons';
import {
Icon,
Pagination,
PaginationEllipsis,
PaginationItem,
PaginationListItem,
PaginationTriggerIconButton,
} from '@vega-ui/react';
import { useState } from 'react';
type PageItem = number | 'start-ellipsis' | 'end-ellipsis';Invalid Composition Patterns
Interactive pagination parts rendered without PaginationListItem
The visuals may still work, but list semantics are weakened.
Pagination component storing the authoritative page state by itself
Canonical page state belongs to the parent feature or router.
Ellipsis used as an interactive substitute for real pages
The shipped ellipsis is a visual gap indicator, not page navigation.