<Pagination.Root>
<Pagination.Content>
<Pagination.Item><Pagination.Previous href="?page=1" /></Pagination.Item>
<Pagination.Item><Pagination.Link href="?page=2" isActive>2</Pagination.Link></Pagination.Item>
<Pagination.Item><Pagination.Ellipsis /></Pagination.Item>
<Pagination.Item><Pagination.Next href="?page=3" /></Pagination.Item>
</Pagination.Content>
</Pagination.Root>These are links, so the page number belongs in the URL. Omit href on
Pagination.Previous or Pagination.Next at the ends of the range and they
render disabled rather than navigating nowhere.
For a paginated table, DataTable has this wired up already.
Windowing the page numbers
usePagination from @voila.dev/ui/hooks turns a page and a page count into
the items to render: zero-based page indexes and PAGINATION_ELLIPSIS where
pages are elided, always the same length so the bar does not jump as the
current page moves. getPaginationRange is the same, outside React.
const items = usePagination({ page, pageCount, siblingCount: 1, boundaryCount: 1 });
<Pagination.Content>
{items.map((item, index) =>
item === PAGINATION_ELLIPSIS ? (
<Pagination.Item key={`gap-${index}`}><Pagination.Ellipsis /></Pagination.Item>
) : (
<Pagination.Item key={item}>
<Pagination.Link isActive={item === page} onClick={() => setPage(item)}>
{item + 1}
</Pagination.Link>
</Pagination.Item>
),
)}
</Pagination.Content>API
Pagination.Root
| Prop | Type | Default | |
|---|---|---|---|
exit | Exit | — | Inside a <Presence>: plays this child's way out before it unmounts. |
render | ComponentRenderFn<HTMLProps, {}> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Plus every <nav> prop. Source: pagination/components/pagination-root.tsx.
Pagination.Content
| Prop | Type | Default | |
|---|---|---|---|
exit | Exit | — | Inside a <Presence>: plays this child's way out before it unmounts. |
render | ComponentRenderFn<HTMLProps, {}> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Plus every <ul> prop. Source: pagination/components/pagination-content.tsx.
Pagination.Ellipsis
| Prop | Type | Default | |
|---|---|---|---|
exit | Exit | — | Inside a <Presence>: plays this child's way out before it unmounts. |
render | ComponentRenderFn<HTMLProps, {}> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Plus every <span> prop. Source: pagination/components/pagination-ellipsis.tsx.
Pagination.Item
| Prop | Type | Default | |
|---|---|---|---|
exit | Exit | — | Inside a <Presence>: plays this child's way out before it unmounts. |
render | ComponentRenderFn<HTMLProps, {}> | ReactElement<unknown, string | JSXElementConstructor<any>> | — | Allows you to replace the component's HTML element
with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render. |
Plus every <li> prop. Source: pagination/components/pagination-item.tsx.
Pagination.Link
| Prop | Type | Default | |
|---|---|---|---|
isActive | boolean | — | |
isDisabled | boolean | — | Render the link as non-interactive (e.g. Previous on the first page):
aria-disabled, removed from the tab order, and dimmed. Maps to the kit's
aria-disabled: styling idiom rather than a dead href. |
size | "default" | "icon" | "icon-lg" | "icon-sm" | "icon-xs" | "lg" | "sm" | "xs" | "icon" | Height and horizontal padding. The icon-* set is square, for a button
whose entire content is one icon — give those an aria-label. |
variant | "brand" | "default" | "destructive" | "ghost" | "highlight" | "link" | "outline" | "primary" | "secondary" | — | Weight of the action. default is the one thing the page exists for, at
most one per view; secondary an equal-weight alternative; outline
for toolbars and anything that repeats in a row; ghost inside dense
surfaces; destructive for what cannot be undone; link for an action
that reads as navigation. |
exit | Exit | — | Inside a <Presence>: plays this child's way out before it unmounts. |
Plus every <a> prop. Source: pagination/components/pagination-link.tsx.
Pagination.Next
| Prop | Type | Default | |
|---|---|---|---|
isActive | boolean | — | |
isDisabled | boolean | — | Render the link as non-interactive (e.g. Previous on the first page):
aria-disabled, removed from the tab order, and dimmed. Maps to the kit's
aria-disabled: styling idiom rather than a dead href. |
size | "default" | "icon" | "icon-lg" | "icon-sm" | "icon-xs" | "lg" | "sm" | "xs" | — | Height and horizontal padding. The icon-* set is square, for a button
whose entire content is one icon — give those an aria-label. |
text | string | "Next" | |
variant | "brand" | "default" | "destructive" | "ghost" | "highlight" | "link" | "outline" | "primary" | "secondary" | — | Weight of the action. default is the one thing the page exists for, at
most one per view; secondary an equal-weight alternative; outline
for toolbars and anything that repeats in a row; ghost inside dense
surfaces; destructive for what cannot be undone; link for an action
that reads as navigation. |
exit | Exit | — | Inside a <Presence>: plays this child's way out before it unmounts. |
Plus the DOM props of the element it renders. Source: pagination/components/pagination-next.tsx.
Pagination.Previous
| Prop | Type | Default | |
|---|---|---|---|
isActive | boolean | — | |
isDisabled | boolean | — | Render the link as non-interactive (e.g. Previous on the first page):
aria-disabled, removed from the tab order, and dimmed. Maps to the kit's
aria-disabled: styling idiom rather than a dead href. |
size | "default" | "icon" | "icon-lg" | "icon-sm" | "icon-xs" | "lg" | "sm" | "xs" | — | Height and horizontal padding. The icon-* set is square, for a button
whose entire content is one icon — give those an aria-label. |
text | string | "Previous" | |
variant | "brand" | "default" | "destructive" | "ghost" | "highlight" | "link" | "outline" | "primary" | "secondary" | — | Weight of the action. default is the one thing the page exists for, at
most one per view; secondary an equal-weight alternative; outline
for toolbars and anything that repeats in a row; ghost inside dense
surfaces; destructive for what cannot be undone; link for an action
that reads as navigation. |
exit | Exit | — | Inside a <Presence>: plays this child's way out before it unmounts. |
Plus the DOM props of the element it renders. Source: pagination/components/pagination-previous.tsx.