Pagination
Overviewimport { Pagination, PaginationAlign, PaginationEllipsis, PaginationLabels, PaginationSlot, PaginationType } from '@nili/ui';This is the library’s own overview page, rendered live. Switch the language or the theme in the header and it follows.
Basic
count is the number of pages; page is 1-based. Uncontrolled with defaultPage, or controlled with page plus onPageChange.
import { Pagination } from "@nili/ui"
export function Example() {
const [page, setPage] = useState(3)
return (
<Pagination
count={16}
page={page}
onPageChange={setPage}
labels={{ root: "Pagination" }}
/>
)
}Types
Basic is separate cells; Full Radius makes them pills; Group joins them into a single segmented control.
import { Pagination } from "@nili/ui"
export function Example() {
return (
<>
<Pagination count={16} defaultPage={3} type="basic" />
<Pagination count={16} defaultPage={3} type="full-radius" />
<Pagination count={16} defaultPage={3} type="group" />
</>
)
}The window
siblingCount is how many pages sit either side of the current one; boundaryCount is how many stay pinned at each end. showEdges adds first/last jumps outside the arrows.
import { Pagination } from "@nili/ui"
export function Example() {
return (
<>
<Pagination count={40} defaultPage={20} siblingCount={1} />
<Pagination count={40} defaultPage={20} siblingCount={2} boundaryCount={2} />
<Pagination count={40} defaultPage={20} showEdges />
</>
)
}Alignment and device mode
align positions the row. The mobile device mode drops the cells for a pair of arrows and a “Page 3 of 16” summary — a sixteen-page trail does not fit on a phone.
import { Pagination } from "@nili/ui"
export function Example() {
return (
<>
<Pagination count={16} defaultPage={3} align="start" />
<Pagination count={16} defaultPage={3} align="between" />
<Pagination count={16} defaultPage={3} deviceMode="mobile" />
</>
)
}Advanced
advanced adds the summary before the trail and the rows-per-page control after it. Every visible string is a prop — a design system that owns its copy forces its translation stack on every consumer.
import { Pagination } from "@nili/ui"
export function Example() {
const [page, setPage] = useState(1)
const [pageSize, setPageSize] = useState(10)
return (
<Pagination
advanced
count={16}
page={page}
onPageChange={setPage}
pageSize={pageSize}
pageSizeOptions={[10, 20, 50]}
onPageSizeChange={setPageSize}
labels={{
root: "Pagination",
summary: (page, count) => `Page ${page} of ${count}`,
perPage: (size) => `${size} / page`,
}}
/>
)
}Disabled
Greys out the whole control — a table that is reloading, for instance.
import { Pagination } from "@nili/ui"
export function Example() {
return <Pagination count={16} defaultPage={3} disabled />
}Pagination
extends Omit< ComponentPropsWithoutRef<'nav'>, 'onChange' | 'children' >
Variant axes — from the component’s cva definition
| Prop | Type | Default | Notes |
|---|---|---|---|
| align | start | center | end | between | center |
Other props
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | — | |
| aria-label | string | — | |
| count* | number | — | Total number of pages. Anything below 1 renders nothing. |
| page | number | — | Current page, 1-based. Controlled. |
| defaultPage | number | 1 | Starting page while uncontrolled. |
| onPageChange | (page: number) => void | — | |
| siblingCount | number | 1 | Pages either side of the current one. |
| boundaryCount | number | 1 | Pages pinned at each end of the trail. |
| type | basic | full-radius | group | basic | |
| deviceMode | desktop | mobile | desktop | Figma's `Device Mode`. `mobile` shows arrows plus a summary, not cells. |
| showEdges | boolean | false | Adds first/last jumps outside the arrows. |
| disabled | boolean | false | Greys out the whole control — a table reloading, for instance. |
| advanced | boolean | false | Figma's `🧪 Advanced`. Adds the "Page 2 of 16" summary before the trail and the rows-per-page control after it. |
| pageSize | number | — | Rows per page. Only rendered when `advanced`. |
| pageSizeOptions | number[] | — | Choices offered by the per-page control. |
| onPageSizeChange | (pageSize: number) => void | — | |
| locale | string | — | BCP-47 tag driving the digits (`'fa'` → Persian). Defaults to the ambient locale from `NiliProvider`. |
| labels | PaginationLabels | — |
PaginationEllipsis
extends Omit< ComponentPropsWithoutRef<'span'>, 'children' >
Variant axes — from the component’s cva definition
| Prop | Type | Default | Notes |
|---|---|---|---|
| fullRadius | boolean | false | Match the cells it sits among. Circles in Figma's Full Radius row. |
Other props
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | — | |
| aria-label | string | — | |
| label | string | More pages | Accessible name; the glyph itself is hidden. |
PaginationGroup
internalPaginationItem
extends Omit< ComponentPropsWithoutRef<'button'>, 'children' >
Variant axes — from the component’s cva definition
| Prop | Type | Default | Notes |
|---|---|---|---|
| active | boolean | false | The page you are on: adds `aria-current="page"`. |
| fullRadius | boolean | false | Figma's `Full Radius`: a pill cell instead of a rounded rectangle. |
Other props
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | — | |
| disabled | boolean | — | |
| required | boolean | — | |
| readOnly | boolean | — | |
| value | string | — | |
| defaultValue | string | — | |
| name | string | — | |
| aria-label | string | — | |
| asChild | boolean | false | Render the child element instead of a `<button>` — for router links. |