@mshafiqyajid/react-pagination
Headless pagination hook and styled component. Ellipsis algorithm, page size selector, controlled and uncontrolled state, multiple variants and sizes, full keyboard and ARIA support.
Playground #
Page 1 of 10 โ showing items 1โ10 of 100
Props
TSX
import { PaginationStyled } from "@mshafiqyajid/react-pagination/styled";
import "@mshafiqyajid/react-pagination/styles.css";
<PaginationStyled />Install #
npm install @mshafiqyajid/react-pagination Quick start #
import { useState } from "react";
import { PaginationStyled } from "@mshafiqyajid/react-pagination/styled";
import "@mshafiqyajid/react-pagination/styles.css";
function App() {
const [page, setPage] = useState(1);
return (
<PaginationStyled
page={page}
onChange={setPage}
total={200}
pageSize={10}
/>
);
} Variants #
Three visual variants: "default" (filled active page), "outline" (bordered buttons), and "ghost" (no borders, bold active).
<PaginationStyled total={100} variant="default" />
<PaginationStyled total={100} variant="outline" />
<PaginationStyled total={100} variant="ghost" /> Tones #
Use tone="primary" to apply a branded color to the active page button.
<PaginationStyled total={100} tone="neutral" />
<PaginationStyled total={100} tone="primary" /> Sizes #
<PaginationStyled total={100} size="sm" />
<PaginationStyled total={100} size="md" />
<PaginationStyled total={100} size="lg" /> Page size selector #
Enable a native <select> for rows-per-page with showPageSize.
const [pageSize, setPageSize] = useState(10);
<PaginationStyled
total={500}
pageSize={pageSize}
onPageSizeChange={setPageSize}
pageSizeOptions={[10, 25, 50, 100]}
showPageSize
/> Ellipsis algorithm #
The siblings prop controls how many page buttons appear on each side of the current page before an ellipsis is shown. boundaries controls how many pages are always shown at the start and end.
{/* Show 2 siblings on each side of current page */}
<PaginationStyled total={500} siblings={2} />
{/* Always show 2 boundary pages at each end */}
<PaginationStyled total={500} boundaries={2} /> Headless #
import { usePagination } from "@mshafiqyajid/react-pagination";
function MyPagination() {
const {
page,
pages,
totalPages,
hasPrev,
hasNext,
prev,
next,
getPageProps,
prevProps,
nextProps,
firstProps,
lastProps,
} = usePagination({ total: 200, pageSize: 10 });
return (
<nav role="navigation" aria-label="Pagination">
<button {...firstProps}>ยซ</button>
<button {...prevProps}>โน</button>
{pages.map((p, i) =>
p === "..." ? (
<span key={`e-${i}`}>โฆ</span>
) : (
<button key={p} {...getPageProps(p)}>{p}</button>
)
)}
<button {...nextProps}>โบ</button>
<button {...lastProps}>ยป</button>
</nav>
);
} API โ PaginationStyled #
| Prop | Type | Default | Description |
|---|---|---|---|
| total | number | โ | Total number of items (required) |
| page | number | โ | Controlled current page (1-based) |
| defaultPage | number | 1 | Uncontrolled initial page |
| onChange | (page: number) => void | โ | Fires when the page changes |
| pageSize | number | 10 | Items per page |
| onPageSizeChange | (size: number) => void | โ | Fires when the page size selector changes |
| pageSizeOptions | number[] | [10, 20, 50, 100] | Options for the page size selector |
| showPageSize | boolean | false | Show the rows-per-page selector |
| siblings | number | 1 | Page buttons on each side of current before ellipsis |
| boundaries | number | 1 | Always-visible pages at each end |
| showFirstLast | boolean | true | Show first/last buttons |
| showPrevNext | boolean | true | Show previous/next buttons |
| size | "sm" | "md" | "lg" | "md" | Button size |
| variant | "default" | "outline" | "ghost" | "default" | Visual style |
| tone | "neutral" | "primary" | "neutral" | Color tone for the active page |
| labels | { prev?, next?, first?, last? } | โ | Override the navigation button labels |
| className | string | โ | Extra class on the root element |
| style | CSSProperties | โ | Inline style override |
API โ usePagination #
| Key | Type | Description |
|---|---|---|
| page | number | Current page (1-based) |
| setPage | (page: number) => void | Navigate to a specific page |
| pages | (number | "...")[] | Ordered array of page numbers and ellipsis markers |
| totalPages | number | Total number of pages |
| hasPrev | boolean | Whether a previous page exists |
| hasNext | boolean | Whether a next page exists |
| prev | () => void | Navigate to the previous page |
| next | () => void | Navigate to the next page |
| getPageProps | (p: number) => ButtonProps | ARIA props for a numbered page button |
| prevProps | ButtonProps | ARIA props for the previous button |
| nextProps | ButtonProps | ARIA props for the next button |
| firstProps | ButtonProps | ARIA props for the first button |
| lastProps | ButtonProps | ARIA props for the last button |