Pagination
A generic pagination control — reusable for tables, slideshows, or any other paged content — with four visual styles.
Overview
Pagination renders first/previous/next/last arrows (each with a hover tooltip) plus a center section that varies by variant:
value— arrows + a "N of Total" display, optionally editable.counter— arrows + one dot (or bar) per page, each clickable — the slideshow use case.buttonOnly— just the four arrows, no center content.table— an items-count label, numbered pages (or thevaluedisplay) in the center, and a rows-per-page selector.
It's fully controlled/uncontrolled for both page and rowsPerPage — own the state yourself and decide what happens on change (e.g. refetch data), or let the component manage itself.
Import
import { Pagination } from '@unflow.io/ui/components/Pagination';Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'value' | 'counter' | 'buttonOnly' | 'table' | 'value' | |
page | number | — | Controlled current page, 1-based |
defaultPage | number | 1 | Seeds the uncontrolled page state. Ignored when page is provided |
onPageChange | (page: number) => void | — | |
pageCount | number | — | Required. Total number of pages |
disabled | boolean | — | |
editablePage | boolean | — | Lets the page number be typed directly. Applies to value, and to table when centerVariant="value" |
hideFirstLast | boolean | — | Hides the first/last (double-chevron) buttons |
disableArrowKeys | boolean | — | Disables the built-in ArrowLeft/ArrowRight handling — turn this on if more than one Pagination is mounted at once |
counterShape | 'dot' | 'bar' | 'dot' | counter variant only |
centerVariant | 'numbered' | 'value' | 'numbered' | table variant only — what renders between the arrows |
itemCount | number | — | table variant — total items, drives the "Showing N items from Total" label |
hideItemsLabel | boolean | — | table variant |
rowsPerPage | number | — | table variant, controlled |
defaultRowsPerPage | number | first of rowsPerPageOptions | table variant, uncontrolled seed |
onRowsPerPageChange | (rows: number) => void | — | table variant |
rowsPerPageOptions | number[] | [10, 25, 50, 100] | table variant |
hideRowsPerPage | boolean | — | table variant |
siblingCount | number | 1 | Numbered-page windowing, table variant with centerVariant="numbered" |
boundaryCount | number | 1 | Numbered-page windowing, table variant with centerVariant="numbered" |
Value
<Pagination page={page} onPageChange={setPage} pageCount={100} />Editable
Set editablePage to let the page number be typed directly instead of only stepped via the arrows — committing (Enter or blur) clamps it to [1, pageCount].
<Pagination editablePage page={page} onPageChange={setPage} pageCount={100} />Counter
Arrows plus one indicator per page — pick this for a small pageCount (e.g. a slideshow), since every page gets its own indicator with no windowing.
<Pagination variant="counter" page={page} onPageChange={setPage} pageCount={5} />Bar shape
<Pagination variant="counter" counterShape="bar" page={page} onPageChange={setPage} pageCount={5} />Button only
Just the four arrows, no center content.
<Pagination variant="buttonOnly" page={page} onPageChange={setPage} pageCount={100} />Table
A three-part row: an items-count label on the left, numbered pages (with ellipsis windowing) in the center, and a rows-per-page selector on the right.
<Pagination
variant="table"
page={page}
onPageChange={setPage}
pageCount={100}
itemCount={1000}
rowsPerPage={rowsPerPage}
onRowsPerPageChange={(next) => {
setRowsPerPage(next);
setPage(1);
}}
/>Value center
For very large pageCounts where a numbered-button list isn't practical, set centerVariant="value" to swap the numbered pages for the same "N of Total" display the standalone value variant uses — editablePage applies here too.
<Pagination
variant="table"
centerVariant="value"
editablePage
page={page}
onPageChange={setPage}
pageCount={100}
itemCount={1000}
rowsPerPage={10}
/>Customization (slots & slotProps)
| Slot | Type | Description |
|---|---|---|
firstIcon / previousIcon / nextIcon / lastIcon | ReactNode | Overrides the corresponding arrow's icon |
| Slot Prop | Props | Description |
|---|---|---|
firstButton / previousButton / nextButton / lastButton | Omit<IIconButton, 'onClick' | 'icon'> | The corresponding arrow's IconButton |
tooltip.first / .previous / .next / .last | Omit<ITooltip, 'content' | 'anchorEl'> | The corresponding arrow's Tooltip |
valueRoot | BaseHTMLProps<HTMLDivElement> | Wrapper around the value variant's "{page} of {pageCount}" pair |
pageValue / totalValue | BaseHTMLProps<HTMLParagraphElement> | The two text pieces of the value display |
pageInput | Omit<IInput, 'value' | 'onChange' | 'type'> | The editable page number field (editablePage) |
counterRoot / counterButton | BaseHTMLProps<HTMLDivElement> / BaseButtonProps<HTMLButtonElement> | The counter variant's row and each dot/bar |
pagesRoot / pageButton / ellipsis | — | The table variant's numbered-page row, each page button, and the ellipsis span |
itemsLabel | BaseHTMLProps<HTMLParagraphElement> | The "Showing N items from Total" label |
rowsPerPageRoot / rowsPerPageLabel / rowsPerPageSelect | — | The rows-per-page group, its label, and the underlying Select |
Accessibility
- The root renders as
<nav aria-label="Pagination">, following the WAI-ARIA pagination pattern. - Every arrow button carries its own
aria-label("First page" / "Previous page" / "Next page" / "Last page") independent of theTooltipthat shows the same text on hover/focus — assistive tech gets the label either way. - First/previous disable on the first page; next/last disable on the last page, rather than silently no-op-ing.
- The current page (numbered button, counter dot/bar) carries
aria-current="page". - ArrowLeft/ArrowRight step the page while focus isn't in an editable field, mirroring
ItemNav's ArrowUp/ArrowDown handling — setdisableArrowKeysif more than onePaginationis mounted on the same page.
ItemNav
A "previous / N of X items / next" control with built-in ArrowUp/ArrowDown keyboard support — the item-navigation control used by Modal, reusable anywhere you browse a set of records.
Grid
A responsive CSS grid layout container. Five breakpoint-aware sizes map to standard column counts (4, 8, or 12) with horizontal margins.