Pagination
A composable, accessible Pagination component for modern React applications.
tsx
import { Pagination } from '@nofinite/nui';Interactive Preview
Loading preview...
A fully accessible, WAI-ARIA compliant pagination component for navigating through pages. Supports first/prev/next/last controls, arrow key navigation, and gap indicators similar to GitHub-style pagination.
Usage
Basic Pagination
tsx
import { Pagination } from '@nofinite/nui';
<Pagination page={1} total={10} onChange={setPage} />;Sibling Page Control
tsx
<Pagination page={page} total={50} siblings={2} onChange={setPage} />Disabled Pagination
tsx
<Pagination page={page} total={10} disabled onChange={setPage} />Page Generation Logic
The component implements adaptive pagination math:
- Displays all pages when total is small
- Shows ellipsis only when more than 2 pages are hidden
- Maintains first + last page visibility
- Uses sibling window around current page
Generated item types:
| Type | Description |
|---|---|
number | Page index |
left-ellipsis | Hidden pages before window |
right-ellipsis | Hidden pages after window |
Variants
tsx
<Pagination page={page} total={10} onChange={setPage} /> // Default
<Pagination siblings={2} page={page} total={100} onChange={setPage} /> // Extended window
<Pagination disabled page={page} total={10} onChange={setPage} /> // Disabled
<Pagination className="custom" page={page} total={10} onChange={setPage} /> // StyledAvailable variants
default— Standard paginationextended— Larger sibling windowdisabled— Interaction blockedstyled— Custom styling override
Guidelines
- Increase
siblingsfor data-heavy navigation - Keep default sibling size for compact UI
- Disable pagination during async loading states
- Avoid large sibling counts on small screens
States
| State | Description |
|---|---|
idle | Default rendering |
active | Current page highlighted |
disabled | Navigation locked |
ellipsis | Hidden page ranges |
focused | Keyboard focus visible |
Keyboard Interaction
| Key | Behavior |
|---|---|
Enter | Navigate to page |
Space | Trigger page button |
Tab | Move focus across buttons |
Accessibility
- Semantic
<nav>with pagination label aria-current="page"for active page- ARIA labels for navigation buttons
- Focus-visible outline for keyboard users
- Ellipsis hidden from assistive tech via
aria-hidden
Best Practices
Do
- Use controlled state for predictable navigation
- Provide meaningful page totals
- Keep sibling count minimal for mobile
- Disable during server pagination fetch
- Maintain visual consistency with design tokens
Don’t
- Hide first/last page in long lists
- Use pagination for small datasets
- Disable without visual feedback
- Overload pagination with extra actions
- Remove focus outline for accessibility
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
page* | number | — | The current active page number (1-indexed) |
total* | number | — | The total number of pages available |
onChange* | (page: number) => void | — | Callback fired when a new page is selected |
siblings | number | 1 | Number of page links to show on each side of the current page. Defaults to 1. |
className | string | — | Custom class name applied to the root navigation element |
disabled | boolean | false | Disables all interaction with the pagination controls |