Pagination
A navigation component that allows users to browse through pages.
Anatomy
To set up the pagination correctly, you'll need to understand its anatomy and how we name its parts.
Each part includes a
data-part
attribute to help identify them in the DOM.
Examples
Learn how to use the Pagination
component in your project. Let's take a look at the most basic
example:
import { Pagination } from '@ark-ui/react/pagination'
export const Basic = () => (
<Pagination.Root count={5000} pageSize={10} siblingCount={2}>
<Pagination.PrevTrigger>Previous Page</Pagination.PrevTrigger>
<Pagination.Context>
{(pagination) =>
pagination.pages.map((page, index) =>
page.type === 'page' ? (
<Pagination.Item key={index} {...page}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis key={index} index={index}>
…
</Pagination.Ellipsis>
),
)
}
</Pagination.Context>
<Pagination.NextTrigger>Next Page</Pagination.NextTrigger>
</Pagination.Root>
)
import { Pagination } from '@ark-ui/solid/pagination'
import { For } from 'solid-js'
export const Basic = () => (
<Pagination.Root count={5000} pageSize={10} siblingCount={2}>
<Pagination.PrevTrigger>Previous Page</Pagination.PrevTrigger>
<Pagination.Context>
{(api) => (
<For each={api().pages}>
{(page, index) =>
page.type === 'page' ? (
<Pagination.Item {...page}>{page.value}</Pagination.Item>
) : (
<Pagination.Ellipsis index={index()}>…</Pagination.Ellipsis>
)
}
</For>
)}
</Pagination.Context>
<Pagination.NextTrigger>Next Page</Pagination.NextTrigger>
</Pagination.Root>
)
<script setup lang="ts">
import { Pagination } from '@ark-ui/vue/pagination'
</script>
<template>
<Pagination.Root :count="100" :page-size="10" :sibling-count="2">
<Pagination.PrevTrigger>
Previous
<span className="visually-hidden">Page</span>
</Pagination.PrevTrigger>
<Pagination.Context v-slot="pagination">
<template v-for="(page, index) in pagination.pages">
<Pagination.Item
v-if="page.type === 'page'"
:key="index"
:value="page.value"
:type="page.type"
>
{{ page.value }}
</Pagination.Item>
<Pagination.Ellipsis v-else :key="'e' + index" :index="index">…</Pagination.Ellipsis>
</template>
</Pagination.Context>
<Pagination.NextTrigger>
Next
<span className="visually-hidden">Page</span>
</Pagination.NextTrigger>
</Pagination.Root>
</template>
Controlled Pagination
To create a controlled Pagination component, manage the state of the current page using the page
prop and update it when the onPageChange
event handler is called:
import { Pagination } from '@ark-ui/react/pagination'
import { useState } from 'react'
export const Controlled = () => {
const [currentPage, setCurrentPage] = useState(1)
return (
<Pagination.Root
count={5000}
pageSize={10}
siblingCount={2}
page={currentPage}
onPageChange={(details) => setCurrentPage(details.page)}
>
<Pagination.PrevTrigger>Previous</Pagination.PrevTrigger>
<Pagination.Context>
{(pagination) =>
pagination.pages.map((page, index) =>
page.type === 'page' ? (
<Pagination.Item key={index} {...page}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis key={index} index={index}>
…
</Pagination.Ellipsis>
),
)
}
</Pagination.Context>
<Pagination.NextTrigger>Next Page</Pagination.NextTrigger>
</Pagination.Root>
)
}
import { Pagination } from '@ark-ui/solid/pagination'
import { For, createSignal } from 'solid-js'
export const Controlled = () => {
const [currentPage, setCurrentPage] = createSignal(1)
return (
<Pagination.Root
count={5000}
pageSize={10}
siblingCount={2}
page={currentPage()}
onPageChange={(details) => setCurrentPage(details.page)}
>
<Pagination.PrevTrigger>Previous Page</Pagination.PrevTrigger>
<Pagination.Context>
{(api) => (
<For each={api().pages}>
{(page, index) =>
page.type === 'page' ? (
<Pagination.Item {...page}>{page.value}</Pagination.Item>
) : (
<Pagination.Ellipsis index={index()}>…</Pagination.Ellipsis>
)
}
</For>
)}
</Pagination.Context>
<Pagination.NextTrigger>Next Page</Pagination.NextTrigger>
</Pagination.Root>
)
}
Example not found
Customizing Pagination
You can customize the Pagination component by setting various props such as dir
, pageSize
,
siblingCount
, and translations
. Here's an example of a customized Pagination:
import { Pagination } from '@ark-ui/react/pagination'
export const Customized = () => (
<Pagination.Root
count={5000}
pageSize={20}
siblingCount={3}
translations={{
nextTriggerLabel: 'Next',
prevTriggerLabel: 'Prev',
itemLabel: (details) => `Page ${details.page}`,
}}
>
<Pagination.PrevTrigger>Previous</Pagination.PrevTrigger>
<Pagination.Context>
{(pagination) =>
pagination.pages.map((page, index) =>
page.type === 'page' ? (
<Pagination.Item key={index} {...page}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis key={index} index={index}>
…
</Pagination.Ellipsis>
),
)
}
</Pagination.Context>
<Pagination.NextTrigger>Next Page</Pagination.NextTrigger>
</Pagination.Root>
)
import { Pagination } from '@ark-ui/solid/pagination'
import { For } from 'solid-js'
export const Customized = () => {
return (
<Pagination.Root
count={5000}
pageSize={20}
siblingCount={3}
translations={{
nextTriggerLabel: 'Next',
prevTriggerLabel: 'Prev',
itemLabel: (details) => `Page ${details.page}`,
}}
>
<Pagination.PrevTrigger>Previous Page</Pagination.PrevTrigger>
<Pagination.Context>
{(api) => (
<For each={api().pages}>
{(page, index) =>
page.type === 'page' ? (
<Pagination.Item {...page}>{page.value}</Pagination.Item>
) : (
<Pagination.Ellipsis index={index()}>…</Pagination.Ellipsis>
)
}
</For>
)}
</Pagination.Context>
<Pagination.NextTrigger>Next Page</Pagination.NextTrigger>
</Pagination.Root>
)
}
<script setup lang="ts">
import { Pagination } from '@ark-ui/vue/pagination'
</script>
<template>
<Pagination.Root
:count="5000"
:page-size="20"
:sibling-count="3"
:translations="{
nextTriggerLabel: 'Next',
prevTriggerLabel: 'Prev',
itemLabel: (details) => `Page ${details.page}`,
}"
>
<Pagination.PrevTrigger>
Previous
<span className="visually-hidden">Page</span>
</Pagination.PrevTrigger>
<Pagination.Context v-slot="pagination">
<template v-for="(page, index) in pagination.pages">
<Pagination.Item
v-if="page.type === 'page'"
:key="index"
:value="page.value"
:type="page.type"
>
{{ page.value }}
</Pagination.Item>
<Pagination.Ellipsis v-else :key="'e' + index" :index="index">…</Pagination.Ellipsis>
</template>
</Pagination.Context>
<Pagination.NextTrigger>
Next
<span className="visually-hidden">Page</span>
</Pagination.NextTrigger>
</Pagination.Root>
</template>
Using the Root Provider
The RootProvider
component provides a context for the pagination. It accepts the value of the usePagination
hook.
You can leverage it to access the component state and methods from outside the pagination.
import { Pagination, usePagination } from '@ark-ui/react/pagination'
export const RootProvider = () => {
const pagination = usePagination({ count: 5000, pageSize: 10, siblingCount: 2 })
return (
<>
<button onClick={() => pagination.goToNextPage()}>Next Page</button>
<Pagination.RootProvider value={pagination}>
<Pagination.PrevTrigger>Previous Page</Pagination.PrevTrigger>
<Pagination.Context>
{(pagination) =>
pagination.pages.map((page, index) =>
page.type === 'page' ? (
<Pagination.Item key={index} {...page}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis key={index} index={index}>
…
</Pagination.Ellipsis>
),
)
}
</Pagination.Context>
<Pagination.NextTrigger>Next Page</Pagination.NextTrigger>
</Pagination.RootProvider>
</>
)
}
import { Pagination, usePagination } from '@ark-ui/solid/pagination'
import { For } from 'solid-js'
export const RootProvider = () => {
const pagination = usePagination({ count: 5000, pageSize: 10, siblingCount: 2 })
return (
<>
<button onClick={() => pagination().goToNextPage()}>Next Page</button>
<Pagination.RootProvider value={pagination}>
<Pagination.PrevTrigger>Previous Page</Pagination.PrevTrigger>
<Pagination.Context>
{(api) => (
<For each={api().pages}>
{(page, index) =>
page.type === 'page' ? (
<Pagination.Item {...page}>{page.value}</Pagination.Item>
) : (
<Pagination.Ellipsis index={index()}>…</Pagination.Ellipsis>
)
}
</For>
)}
</Pagination.Context>
<Pagination.NextTrigger>Next Page</Pagination.NextTrigger>
</Pagination.RootProvider>
</>
)
}
<script setup lang="ts">
import { Pagination, usePagination } from '@ark-ui/vue/pagination'
const pagination = usePagination({ count: 100, pageSize: 10, siblingCount: 2 })
</script>
<template>
<button @click="pagination.goToNextPage()">Next Page</button>
<Pagination.RootProvider :value="pagination">
<Pagination.PrevTrigger>
Previous
<span className="visually-hidden">Page</span>
</Pagination.PrevTrigger>
<Pagination.Context v-slot="pagination">
<template v-for="(page, index) in pagination.pages">
<Pagination.Item
v-if="page.type === 'page'"
:key="index"
:value="page.value"
:type="page.type"
>
{{ page.value }}
</Pagination.Item>
<Pagination.Ellipsis v-else :key="'e' + index" :index="index">…</Pagination.Ellipsis>
</template>
</Pagination.Context>
<Pagination.NextTrigger>
Next
<span className="visually-hidden">Page</span>
</Pagination.NextTrigger>
</Pagination.RootProvider>
</template>
If you're using the
RootProvider
component, you don't need to use theRoot
component.
API Reference
Root
Prop | Default | Type |
---|---|---|
count | number Total number of data items | |
asChild | (props: ParentProps<'nav'>) => Element Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
defaultPage | number The initial page of the pagination when it is first rendered. Use when you do not need to control the state of the pagination. | |
ids | Partial<{
root: string
ellipsis(index: number): string
prevTrigger: string
nextTrigger: string
item(page: number): string
}> The ids of the elements in the accordion. Useful for composition. | |
onPageChange | (details: PageChangeDetails) => void Called when the page number is changed | |
onPageSizeChange | (details: PageSizeChangeDetails) => void Called when the page size is changed | |
page | 1 | number The active page |
pageSize | 10 | number Number of data items per page |
siblingCount | 1 | number Number of pages to show beside active page |
translations | IntlTranslations Specifies the localized strings that identifies the accessibility elements and their states | |
type | 'button' | 'link' | 'button' The type of the trigger element |
Ellipsis
Prop | Default | Type |
---|---|---|
index | number | |
asChild | (props: ParentProps<'div'>) => Element Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Item
Prop | Default | Type |
---|---|---|
type | 'page' | |
value | number | |
asChild | (props: ParentProps<'button'>) => Element Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Data Attribute | Value |
---|---|
[data-scope] | pagination |
[data-part] | item |
[data-index] | The index of the item |
[data-selected] | Present when selected |
NextTrigger
Prop | Default | Type |
---|---|---|
asChild | (props: ParentProps<'button'>) => Element Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Data Attribute | Value |
---|---|
[data-scope] | pagination |
[data-part] | next-trigger |
[data-disabled] | Present when disabled |
PrevTrigger
Prop | Default | Type |
---|---|---|
asChild | (props: ParentProps<'button'>) => Element Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Data Attribute | Value |
---|---|
[data-scope] | pagination |
[data-part] | prev-trigger |
[data-disabled] | Present when disabled |
RootProvider
Prop | Default | Type |
---|---|---|
value | UsePaginationReturn | |
asChild | (props: ParentProps<'nav'>) => Element Use the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |