Pagination
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 usage
import { Pagination } from '@nofinite/nui';
import { useState } from 'react';
const Page = () => {
const [page, setPage] = useState(1);
return <Pagination page={page} total={10} onChange={setPage} />;
};
With typical interaction
<Pagination
page={currentPage}
total={20}
siblings={2}
onChange={(p) => setCurrentPage(p)}
/>
Variants
Pagination does not have visual variants but supports active and disabled states for buttons.
Available visual states:
active– highlights the current page.disabled– prevents interaction for prev/next buttons at boundaries.
Guidelines:
- Active state always reflects the current page.
- Disabled state applies automatically to first/last or prev/next buttons when at edges.
Sizes
Pagination uses a fixed size based on CSS variables. No size props are currently exposed.
CSS-based sizing:
- Buttons are 32px height with padding 0 8px.
- Full-width behavior can be customized using container styling.
<nav style={{ width: '100%' }}>
<Pagination page={page} total={10} onChange={setPage} />
</nav>
States
<Pagination page={1} total={10} />
<Pagination page={10} total={10} />
active– highlights the currently selected page.disabled– disables prev button on first page, next button on last page.- Ellipsis (
...) – indicates skipped page ranges.
Native Props / Composition
<Pagination
className="custom-pagination"
page={page}
total={10}
onChange={setPage}
/>
Supports standard HTML attributes via className for styling. Fully theme-aware.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
page | number | — | Current active page (1-based) |
total | number | — | Total number of pages |
onChange | (p: number) => void | — | Callback invoked when page changes |
siblings | number | 1 | Number of page buttons to show on either side of active page |
className | string | "" | Additional CSS classes for styling |
Behavior Notes
- GitHub-style pagination logic prevents duplicate pages.
- Automatically inserts ellipsis (
...) when gaps exist between first/last and active pages. - Controlled component:
pagemust be managed by parent state. - Handles edge cases: disables prev/next buttons on first/last pages.
<Pagination page={1} total={5} onChange={setPage} />
Accessibility
- Renders as:
<nav>containing<button>elements. - Keyboard support: Tab to focus buttons, Enter/Space to activate.
aria-label="Pagination Navigation"on nav.aria-current="page"on active page button.- Ellipsis spans are ignored by screen readers.
Example:
<Pagination page={2} total={10} onChange={setPage} />
Layout
- Inline-flex layout with gap between buttons.
- Buttons have min-width of 32px; container can be full-width.
- Works well in any flex or block container.
<Pagination className="w-full" page={3} total={15} onChange={setPage} />
Best Practices
Do
- Use
Paginationfor large datasets split across multiple pages. - Keep
siblingslow for compact layouts; increase for more context. - Use
classNamefor theme-aware styling adjustments.
Don’t
- Avoid uncontrolled usage; always manage
pagestate in parent. - Don’t rely on default styling for critical accessibility cues.
- Avoid nesting multiple
Paginationcomponents for the same data set.