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-partattribute 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 { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'
import { Pagination } from '@ark-ui/react/pagination'
import styles from 'styles/pagination.module.css'
export const Basic = () => (
<Pagination.Root count={5000} pageSize={10} siblingCount={2} className={styles.Root}>
<div className={styles.Controls}>
<Pagination.PrevTrigger className={styles.Trigger}>
<ChevronLeftIcon />
</Pagination.PrevTrigger>
<Pagination.Context>
{(pagination) =>
pagination.pages.map((page, index) =>
page.type === 'page' ? (
<Pagination.Item key={index} {...page} className={styles.Item}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis key={index} index={index} className={styles.Ellipsis}>
…
</Pagination.Ellipsis>
),
)
}
</Pagination.Context>
<Pagination.NextTrigger className={styles.Trigger}>
<ChevronRightIcon />
</Pagination.NextTrigger>
</div>
</Pagination.Root>
)
import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid'
import { Pagination } from '@ark-ui/solid/pagination'
import { For } from 'solid-js'
import styles from 'styles/pagination.module.css'
export const Basic = () => (
<Pagination.Root count={5000} pageSize={10} siblingCount={2} class={styles.Root}>
<div class={styles.Controls}>
<Pagination.PrevTrigger class={styles.Trigger}>
<ChevronLeftIcon />
</Pagination.PrevTrigger>
<Pagination.Context>
{(pagination) => (
<For each={pagination().pages}>
{(page, index) =>
page.type === 'page' ? (
<Pagination.Item {...page} class={styles.Item}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis index={index()} class={styles.Ellipsis}>
…
</Pagination.Ellipsis>
)
}
</For>
)}
</Pagination.Context>
<Pagination.NextTrigger class={styles.Trigger}>
<ChevronRightIcon />
</Pagination.NextTrigger>
</div>
</Pagination.Root>
)
<script setup lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
import { Pagination } from '@ark-ui/vue/pagination'
import styles from 'styles/pagination.module.css'
</script>
<template>
<Pagination.Root :count="5000" :page-size="10" :sibling-count="2" :class="styles.Root">
<div :class="styles.Controls">
<Pagination.PrevTrigger :class="styles.Trigger">
<ChevronLeft />
</Pagination.PrevTrigger>
<Pagination.Context v-slot="pagination">
<template v-for="(page, index) in pagination.pages" :key="index">
<Pagination.Item v-if="page.type === 'page'" v-bind="page" :class="styles.Item">
{{ page.value }}
</Pagination.Item>
<Pagination.Ellipsis v-else :index="index" :class="styles.Ellipsis">…</Pagination.Ellipsis>
</template>
</Pagination.Context>
<Pagination.NextTrigger :class="styles.Trigger">
<ChevronRight />
</Pagination.NextTrigger>
</div>
</Pagination.Root>
</template>
<script lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-svelte'
import { Pagination } from '@ark-ui/svelte/pagination'
import styles from 'styles/pagination.module.css'
</script>
<Pagination.Root count={5000} pageSize={10} siblingCount={2} class={styles.Root}>
<div class={styles.Controls}>
<Pagination.PrevTrigger class={styles.Trigger}>
<ChevronLeft />
</Pagination.PrevTrigger>
<Pagination.Context>
{#snippet render(pagination)}
{#each pagination().pages as page, index (index)}
{#if page.type === 'page'}
<Pagination.Item {...page} class={styles.Item}>
{page.value}
</Pagination.Item>
{:else}
<Pagination.Ellipsis {index} class={styles.Ellipsis}>…</Pagination.Ellipsis>
{/if}
{/each}
{/snippet}
</Pagination.Context>
<Pagination.NextTrigger class={styles.Trigger}>
<ChevronRight />
</Pagination.NextTrigger>
</div>
</Pagination.Root>
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 { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'
import { useState } from 'react'
import { Pagination } from '@ark-ui/react/pagination'
import styles from 'styles/pagination.module.css'
export const Controlled = () => {
const [currentPage, setCurrentPage] = useState(1)
return (
<Pagination.Root
count={5000}
pageSize={10}
siblingCount={2}
page={currentPage}
onPageChange={(details) => setCurrentPage(details.page)}
className={styles.Root}
>
<div className={styles.Controls}>
<Pagination.PrevTrigger className={styles.Trigger}>
<ChevronLeftIcon />
</Pagination.PrevTrigger>
<Pagination.Context>
{(pagination) =>
pagination.pages.map((page, index) =>
page.type === 'page' ? (
<Pagination.Item key={index} {...page} className={styles.Item}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis key={index} index={index} className={styles.Ellipsis}>
…
</Pagination.Ellipsis>
),
)
}
</Pagination.Context>
<Pagination.NextTrigger className={styles.Trigger}>
<ChevronRightIcon />
</Pagination.NextTrigger>
</div>
</Pagination.Root>
)
}
import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid'
import { Pagination } from '@ark-ui/solid/pagination'
import { For, createSignal } from 'solid-js'
import styles from 'styles/pagination.module.css'
export const Controlled = () => {
const [currentPage, setCurrentPage] = createSignal(1)
return (
<Pagination.Root
count={5000}
pageSize={10}
siblingCount={2}
page={currentPage()}
onPageChange={(details) => setCurrentPage(details.page)}
class={styles.Root}
>
<div class={styles.Controls}>
<Pagination.PrevTrigger class={styles.Trigger}>
<ChevronLeftIcon />
</Pagination.PrevTrigger>
<Pagination.Context>
{(pagination) => (
<For each={pagination().pages}>
{(page, index) =>
page.type === 'page' ? (
<Pagination.Item {...page} class={styles.Item}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis index={index()} class={styles.Ellipsis}>
…
</Pagination.Ellipsis>
)
}
</For>
)}
</Pagination.Context>
<Pagination.NextTrigger class={styles.Trigger}>
<ChevronRightIcon />
</Pagination.NextTrigger>
</div>
</Pagination.Root>
)
}
<script setup lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
import { Pagination } from '@ark-ui/vue/pagination'
import { ref } from 'vue'
import styles from 'styles/pagination.module.css'
const currentPage = ref(1)
</script>
<template>
<Pagination.Root :count="5000" :page-size="10" :sibling-count="2" v-model:page="currentPage" :class="styles.Root">
<div :class="styles.Controls">
<Pagination.PrevTrigger :class="styles.Trigger">
<ChevronLeft />
</Pagination.PrevTrigger>
<Pagination.Context v-slot="pagination">
<template v-for="(page, index) in pagination.pages" :key="index">
<Pagination.Item v-if="page.type === 'page'" v-bind="page" :class="styles.Item">
{{ page.value }}
</Pagination.Item>
<Pagination.Ellipsis v-else :index="index" :class="styles.Ellipsis">…</Pagination.Ellipsis>
</template>
</Pagination.Context>
<Pagination.NextTrigger :class="styles.Trigger">
<ChevronRight />
</Pagination.NextTrigger>
</div>
</Pagination.Root>
</template>
<script lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-svelte'
import { Pagination } from '@ark-ui/svelte/pagination'
import styles from 'styles/pagination.module.css'
let page = $state(1)
</script>
<Pagination.Root count={5000} pageSize={10} siblingCount={2} bind:page class={styles.Root}>
<div class={styles.Controls}>
<Pagination.PrevTrigger class={styles.Trigger}>
<ChevronLeft />
</Pagination.PrevTrigger>
<Pagination.Context>
{#snippet render(pagination)}
{#each pagination().pages as page, index (index)}
{#if page.type === 'page'}
<Pagination.Item {...page} class={styles.Item}>
{page.value}
</Pagination.Item>
{:else}
<Pagination.Ellipsis {index} class={styles.Ellipsis}>…</Pagination.Ellipsis>
{/if}
{/each}
{/snippet}
</Pagination.Context>
<Pagination.NextTrigger class={styles.Trigger}>
<ChevronRight />
</Pagination.NextTrigger>
</div>
</Pagination.Root>
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 { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'
import { Pagination } from '@ark-ui/react/pagination'
import styles from 'styles/pagination.module.css'
export const Customized = () => (
<Pagination.Root
count={5000}
pageSize={20}
siblingCount={3}
translations={{
nextTriggerLabel: 'Next',
prevTriggerLabel: 'Prev',
itemLabel: (details) => `Page ${details.page}`,
}}
className={styles.Root}
>
<div className={styles.Controls}>
<Pagination.PrevTrigger className={styles.Trigger}>
<ChevronLeftIcon />
</Pagination.PrevTrigger>
<Pagination.Context>
{(pagination) =>
pagination.pages.map((page, index) =>
page.type === 'page' ? (
<Pagination.Item key={index} {...page} className={styles.Item}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis key={index} index={index} className={styles.Ellipsis}>
…
</Pagination.Ellipsis>
),
)
}
</Pagination.Context>
<Pagination.NextTrigger className={styles.Trigger}>
<ChevronRightIcon />
</Pagination.NextTrigger>
</div>
</Pagination.Root>
)
import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid'
import { Pagination } from '@ark-ui/solid/pagination'
import { For } from 'solid-js'
import styles from 'styles/pagination.module.css'
export const Customized = () => {
return (
<Pagination.Root
count={5000}
pageSize={20}
siblingCount={3}
translations={{
nextTriggerLabel: 'Next',
prevTriggerLabel: 'Prev',
itemLabel: (details) => `Page ${details.page}`,
}}
class={styles.Root}
>
<div class={styles.Controls}>
<Pagination.PrevTrigger class={styles.Trigger}>
<ChevronLeftIcon />
</Pagination.PrevTrigger>
<Pagination.Context>
{(pagination) => (
<For each={pagination().pages}>
{(page, index) =>
page.type === 'page' ? (
<Pagination.Item {...page} class={styles.Item}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis index={index()} class={styles.Ellipsis}>
…
</Pagination.Ellipsis>
)
}
</For>
)}
</Pagination.Context>
<Pagination.NextTrigger class={styles.Trigger}>
<ChevronRightIcon />
</Pagination.NextTrigger>
</div>
</Pagination.Root>
)
}
<script setup lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
import { Pagination } from '@ark-ui/vue/pagination'
import styles from 'styles/pagination.module.css'
</script>
<template>
<Pagination.Root
:count="5000"
:page-size="20"
:sibling-count="3"
:translations="{
nextTriggerLabel: 'Next',
prevTriggerLabel: 'Prev',
itemLabel: (details) => `Page ${details.page}`,
}"
:class="styles.Root"
>
<div :class="styles.Controls">
<Pagination.PrevTrigger :class="styles.Trigger">
<ChevronLeft />
</Pagination.PrevTrigger>
<Pagination.Context v-slot="pagination">
<template v-for="(page, index) in pagination.pages" :key="index">
<Pagination.Item v-if="page.type === 'page'" v-bind="page" :class="styles.Item">
{{ page.value }}
</Pagination.Item>
<Pagination.Ellipsis v-else :index="index" :class="styles.Ellipsis">…</Pagination.Ellipsis>
</template>
</Pagination.Context>
<Pagination.NextTrigger :class="styles.Trigger">
<ChevronRight />
</Pagination.NextTrigger>
</div>
</Pagination.Root>
</template>
<script lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-svelte'
import { Pagination } from '@ark-ui/svelte/pagination'
import styles from 'styles/pagination.module.css'
</script>
<Pagination.Root
count={5000}
pageSize={20}
siblingCount={3}
translations={{
nextTriggerLabel: 'Next',
prevTriggerLabel: 'Prev',
itemLabel: (details) => `Page ${details.page}`,
}}
class={styles.Root}
>
<div class={styles.Controls}>
<Pagination.PrevTrigger class={styles.Trigger}>
<ChevronLeft />
</Pagination.PrevTrigger>
<Pagination.Context>
{#snippet render(pagination)}
{#each pagination().pages as page, index (index)}
{#if page.type === 'page'}
<Pagination.Item {...page} class={styles.Item}>
{page.value}
</Pagination.Item>
{:else}
<Pagination.Ellipsis {index} class={styles.Ellipsis}>…</Pagination.Ellipsis>
{/if}
{/each}
{/snippet}
</Pagination.Context>
<Pagination.NextTrigger class={styles.Trigger}>
<ChevronRight />
</Pagination.NextTrigger>
</div>
</Pagination.Root>
Using Context
The Context component provides access to the pagination state and methods through a render prop pattern. This allows
you to access methods like setPage, setPageSize, goToNextPage, goToPrevPage, goToFirstPage, goToLastPage, as
well as properties like totalPages and pageRange.
import { ChevronLeftIcon, ChevronRightIcon, ChevronsLeftIcon, ChevronsRightIcon } from 'lucide-react'
import { Pagination } from '@ark-ui/react/pagination'
import styles from 'styles/pagination.module.css'
export const Context = () => {
return (
<Pagination.Root count={100} pageSize={10} className={styles.Root}>
<Pagination.Context>
{(pagination) => (
<div className={styles.Controls}>
<button className={styles.Trigger} onClick={() => pagination.goToFirstPage()}>
<ChevronsLeftIcon />
</button>
<button className={styles.Trigger} onClick={() => pagination.goToPrevPage()}>
<ChevronLeftIcon />
</button>
<p className={styles.Text} style={{ minWidth: '120px', textAlign: 'center' }}>
Page {pagination.page} of {pagination.totalPages}
</p>
<button className={styles.Trigger} onClick={() => pagination.goToNextPage()}>
<ChevronRightIcon />
</button>
<button className={styles.Trigger} onClick={() => pagination.goToLastPage()}>
<ChevronsRightIcon />
</button>
</div>
)}
</Pagination.Context>
</Pagination.Root>
)
}
import { ChevronLeftIcon, ChevronRightIcon, ChevronsLeftIcon, ChevronsRightIcon } from 'lucide-solid'
import { Pagination } from '@ark-ui/solid/pagination'
import styles from 'styles/pagination.module.css'
export const Context = () => {
return (
<Pagination.Root count={100} pageSize={10} class={styles.Root}>
<Pagination.Context>
{(pagination) => (
<div class={styles.Controls}>
<button class={styles.Trigger} onClick={() => pagination().goToFirstPage()}>
<ChevronsLeftIcon />
</button>
<button class={styles.Trigger} onClick={() => pagination().goToPrevPage()}>
<ChevronLeftIcon />
</button>
<p class={styles.Text} style={{ 'min-width': '120px', 'text-align': 'center' }}>
Page {pagination().page} of {pagination().totalPages}
</p>
<button class={styles.Trigger} onClick={() => pagination().goToNextPage()}>
<ChevronRightIcon />
</button>
<button class={styles.Trigger} onClick={() => pagination().goToLastPage()}>
<ChevronsRightIcon />
</button>
</div>
)}
</Pagination.Context>
</Pagination.Root>
)
}
<script setup lang="ts">
import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide-vue-next'
import { Pagination } from '@ark-ui/vue/pagination'
import styles from 'styles/pagination.module.css'
</script>
<template>
<Pagination.Root :count="100" :page-size="10" :class="styles.Root">
<Pagination.Context v-slot="pagination">
<div :class="styles.Controls">
<button :class="styles.Trigger" @click="pagination.goToFirstPage()">
<ChevronsLeft />
</button>
<button :class="styles.Trigger" @click="pagination.goToPrevPage()">
<ChevronLeft />
</button>
<p :class="styles.Text" style="min-width: 120px; text-align: center">
Page {{ pagination.page }} of {{ pagination.totalPages }}
</p>
<button :class="styles.Trigger" @click="pagination.goToNextPage()">
<ChevronRight />
</button>
<button :class="styles.Trigger" @click="pagination.goToLastPage()">
<ChevronsRight />
</button>
</div>
</Pagination.Context>
</Pagination.Root>
</template>
<script lang="ts">
import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide-svelte'
import { Pagination } from '@ark-ui/svelte/pagination'
import styles from 'styles/pagination.module.css'
</script>
<Pagination.Root count={100} pageSize={10} class={styles.Root}>
<Pagination.Context>
{#snippet render(pagination)}
<div class={styles.Controls}>
<button class={styles.Trigger} onclick={() => pagination().goToFirstPage()}>
<ChevronsLeft />
</button>
<button class={styles.Trigger} onclick={() => pagination().goToPrevPage()}>
<ChevronLeft />
</button>
<p class={styles.Text} style="min-width: 120px; text-align: center;">
Page {pagination().page} of {pagination().totalPages}
</p>
<button class={styles.Trigger} onclick={() => pagination().goToNextPage()}>
<ChevronRight />
</button>
<button class={styles.Trigger} onclick={() => pagination().goToLastPage()}>
<ChevronsRight />
</button>
</div>
{/snippet}
</Pagination.Context>
</Pagination.Root>
Data Slicing
Use the slice() method to paginate actual data arrays. This method automatically slices your data based on the current
page and page size.
import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'
import { Pagination } from '@ark-ui/react/pagination'
import styles from 'styles/pagination.module.css'
const users = [
{ id: 1, name: 'Emma Wilson', email: 'emma@example.com' },
{ id: 2, name: 'Liam Johnson', email: 'liam@example.com' },
{ id: 3, name: 'Olivia Brown', email: 'olivia@example.com' },
{ id: 4, name: 'Noah Davis', email: 'noah@example.com' },
{ id: 5, name: 'Ava Martinez', email: 'ava@example.com' },
{ id: 6, name: 'Ethan Garcia', email: 'ethan@example.com' },
{ id: 7, name: 'Sophia Rodriguez', email: 'sophia@example.com' },
{ id: 8, name: 'Mason Lee', email: 'mason@example.com' },
{ id: 9, name: 'Isabella Walker', email: 'isabella@example.com' },
{ id: 10, name: 'James Hall', email: 'james@example.com' },
{ id: 11, name: 'Mia Allen', email: 'mia@example.com' },
{ id: 12, name: 'Benjamin Young', email: 'benjamin@example.com' },
{ id: 13, name: 'Charlotte King', email: 'charlotte@example.com' },
{ id: 14, name: 'William Wright', email: 'william@example.com' },
{ id: 15, name: 'Amelia Scott', email: 'amelia@example.com' },
{ id: 16, name: 'Henry Green', email: 'henry@example.com' },
{ id: 17, name: 'Harper Adams', email: 'harper@example.com' },
{ id: 18, name: 'Sebastian Baker', email: 'sebastian@example.com' },
{ id: 19, name: 'Evelyn Nelson', email: 'evelyn@example.com' },
{ id: 20, name: 'Jack Carter', email: 'jack@example.com' },
]
export const DataSlicing = () => {
return (
<Pagination.Root count={users.length} pageSize={5} className={styles.Root}>
<Pagination.Context>
{(pagination) => (
<>
<div className={styles.Grid}>
{pagination.slice(users).map((user) => (
<div key={user.id} className={styles.GridItem}>
<span className={styles.GridItemTitle}>{user.name}</span>
<span className={styles.GridItemText}>{user.email}</span>
</div>
))}
</div>
<div className={styles.Controls}>
<Pagination.PrevTrigger className={styles.Trigger}>
<ChevronLeftIcon />
</Pagination.PrevTrigger>
{pagination.pages.map((page, index) =>
page.type === 'page' ? (
<Pagination.Item key={index} {...page} className={styles.Item}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis key={index} index={index} className={styles.Ellipsis}>
…
</Pagination.Ellipsis>
),
)}
<Pagination.NextTrigger className={styles.Trigger}>
<ChevronRightIcon />
</Pagination.NextTrigger>
</div>
</>
)}
</Pagination.Context>
</Pagination.Root>
)
}
import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid'
import { Pagination } from '@ark-ui/solid/pagination'
import { For } from 'solid-js'
import styles from 'styles/pagination.module.css'
const users = [
{ id: 1, name: 'Emma Wilson', email: 'emma@example.com' },
{ id: 2, name: 'Liam Johnson', email: 'liam@example.com' },
{ id: 3, name: 'Olivia Brown', email: 'olivia@example.com' },
{ id: 4, name: 'Noah Davis', email: 'noah@example.com' },
{ id: 5, name: 'Ava Martinez', email: 'ava@example.com' },
{ id: 6, name: 'Ethan Garcia', email: 'ethan@example.com' },
{ id: 7, name: 'Sophia Rodriguez', email: 'sophia@example.com' },
{ id: 8, name: 'Mason Lee', email: 'mason@example.com' },
{ id: 9, name: 'Isabella Walker', email: 'isabella@example.com' },
{ id: 10, name: 'James Hall', email: 'james@example.com' },
{ id: 11, name: 'Mia Allen', email: 'mia@example.com' },
{ id: 12, name: 'Benjamin Young', email: 'benjamin@example.com' },
{ id: 13, name: 'Charlotte King', email: 'charlotte@example.com' },
{ id: 14, name: 'William Wright', email: 'william@example.com' },
{ id: 15, name: 'Amelia Scott', email: 'amelia@example.com' },
{ id: 16, name: 'Henry Green', email: 'henry@example.com' },
{ id: 17, name: 'Harper Adams', email: 'harper@example.com' },
{ id: 18, name: 'Sebastian Baker', email: 'sebastian@example.com' },
{ id: 19, name: 'Evelyn Nelson', email: 'evelyn@example.com' },
{ id: 20, name: 'Jack Carter', email: 'jack@example.com' },
]
export const DataSlicing = () => {
return (
<Pagination.Root count={users.length} pageSize={5} class={styles.Root}>
<Pagination.Context>
{(pagination) => (
<>
<div class={styles.Grid}>
<For each={pagination().slice(users)}>
{(user) => (
<div class={styles.GridItem}>
<span class={styles.GridItemTitle}>{user.name}</span>
<span class={styles.GridItemText}>{user.email}</span>
</div>
)}
</For>
</div>
<div class={styles.Controls}>
<Pagination.PrevTrigger class={styles.Trigger}>
<ChevronLeftIcon />
</Pagination.PrevTrigger>
<For each={pagination().pages}>
{(page, index) =>
page.type === 'page' ? (
<Pagination.Item {...page} class={styles.Item}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis index={index()} class={styles.Ellipsis}>
…
</Pagination.Ellipsis>
)
}
</For>
<Pagination.NextTrigger class={styles.Trigger}>
<ChevronRightIcon />
</Pagination.NextTrigger>
</div>
</>
)}
</Pagination.Context>
</Pagination.Root>
)
}
<script setup lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
import { Pagination } from '@ark-ui/vue/pagination'
import styles from 'styles/pagination.module.css'
const users = [
{ id: 1, name: 'Emma Wilson', email: 'emma@example.com' },
{ id: 2, name: 'Liam Johnson', email: 'liam@example.com' },
{ id: 3, name: 'Olivia Brown', email: 'olivia@example.com' },
{ id: 4, name: 'Noah Davis', email: 'noah@example.com' },
{ id: 5, name: 'Ava Martinez', email: 'ava@example.com' },
{ id: 6, name: 'Ethan Garcia', email: 'ethan@example.com' },
{ id: 7, name: 'Sophia Rodriguez', email: 'sophia@example.com' },
{ id: 8, name: 'Mason Lee', email: 'mason@example.com' },
{ id: 9, name: 'Isabella Walker', email: 'isabella@example.com' },
{ id: 10, name: 'James Hall', email: 'james@example.com' },
{ id: 11, name: 'Mia Allen', email: 'mia@example.com' },
{ id: 12, name: 'Benjamin Young', email: 'benjamin@example.com' },
{ id: 13, name: 'Charlotte King', email: 'charlotte@example.com' },
{ id: 14, name: 'William Wright', email: 'william@example.com' },
{ id: 15, name: 'Amelia Scott', email: 'amelia@example.com' },
{ id: 16, name: 'Henry Green', email: 'henry@example.com' },
{ id: 17, name: 'Harper Adams', email: 'harper@example.com' },
{ id: 18, name: 'Sebastian Baker', email: 'sebastian@example.com' },
{ id: 19, name: 'Evelyn Nelson', email: 'evelyn@example.com' },
{ id: 20, name: 'Jack Carter', email: 'jack@example.com' },
]
</script>
<template>
<Pagination.Root :count="users.length" :page-size="5" :class="styles.Root">
<Pagination.Context v-slot="pagination">
<div :class="styles.Grid">
<div v-for="user in pagination.slice(users)" :key="user.id" :class="styles.GridItem">
<span :class="styles.GridItemTitle">{{ user.name }}</span>
<span :class="styles.GridItemText">{{ user.email }}</span>
</div>
</div>
<div :class="styles.Controls">
<Pagination.PrevTrigger :class="styles.Trigger">
<ChevronLeft />
</Pagination.PrevTrigger>
<template v-for="(page, index) in pagination.pages" :key="index">
<Pagination.Item v-if="page.type === 'page'" v-bind="page" :class="styles.Item">
{{ page.value }}
</Pagination.Item>
<Pagination.Ellipsis v-else :index="index" :class="styles.Ellipsis">…</Pagination.Ellipsis>
</template>
<Pagination.NextTrigger :class="styles.Trigger">
<ChevronRight />
</Pagination.NextTrigger>
</div>
</Pagination.Context>
</Pagination.Root>
</template>
<script lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-svelte'
import { Pagination } from '@ark-ui/svelte/pagination'
import styles from 'styles/pagination.module.css'
const users = [
{ id: 1, name: 'Emma Wilson', email: 'emma@example.com' },
{ id: 2, name: 'Liam Johnson', email: 'liam@example.com' },
{ id: 3, name: 'Olivia Brown', email: 'olivia@example.com' },
{ id: 4, name: 'Noah Davis', email: 'noah@example.com' },
{ id: 5, name: 'Ava Martinez', email: 'ava@example.com' },
{ id: 6, name: 'Ethan Garcia', email: 'ethan@example.com' },
{ id: 7, name: 'Sophia Rodriguez', email: 'sophia@example.com' },
{ id: 8, name: 'Mason Lee', email: 'mason@example.com' },
{ id: 9, name: 'Isabella Walker', email: 'isabella@example.com' },
{ id: 10, name: 'James Hall', email: 'james@example.com' },
{ id: 11, name: 'Mia Allen', email: 'mia@example.com' },
{ id: 12, name: 'Benjamin Young', email: 'benjamin@example.com' },
{ id: 13, name: 'Charlotte King', email: 'charlotte@example.com' },
{ id: 14, name: 'William Wright', email: 'william@example.com' },
{ id: 15, name: 'Amelia Scott', email: 'amelia@example.com' },
{ id: 16, name: 'Henry Green', email: 'henry@example.com' },
{ id: 17, name: 'Harper Adams', email: 'harper@example.com' },
{ id: 18, name: 'Sebastian Baker', email: 'sebastian@example.com' },
{ id: 19, name: 'Evelyn Nelson', email: 'evelyn@example.com' },
{ id: 20, name: 'Jack Carter', email: 'jack@example.com' },
]
</script>
<Pagination.Root count={users.length} pageSize={5} class={styles.Root}>
<Pagination.Context>
{#snippet render(pagination)}
<div class={styles.Grid}>
{#each pagination().slice(users) as user (user.id)}
<div class={styles.GridItem}>
<span class={styles.GridItemTitle}>{user.name}</span>
<span class={styles.GridItemText}>{user.email}</span>
</div>
{/each}
</div>
<div class={styles.Controls}>
<Pagination.PrevTrigger class={styles.Trigger}>
<ChevronLeft />
</Pagination.PrevTrigger>
{#each pagination().pages as page, index}
{#if page.type === 'page'}
<Pagination.Item {...page} class={styles.Item}>{page.value}</Pagination.Item>
{:else}
<Pagination.Ellipsis {index} class={styles.Ellipsis}>…</Pagination.Ellipsis>
{/if}
{/each}
<Pagination.NextTrigger class={styles.Trigger}>
<ChevronRight />
</Pagination.NextTrigger>
</div>
{/snippet}
</Pagination.Context>
</Pagination.Root>
Page Range Display
Display the current page range information using the pageRange property. This shows which items are currently visible
(e.g., "Showing 1-10 of 100 results").
import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'
import { Pagination } from '@ark-ui/react/pagination'
import styles from 'styles/pagination.module.css'
export const PageRange = () => {
return (
<Pagination.Root count={100} pageSize={10} className={styles.Root}>
<Pagination.Context>
{(pagination) => (
<>
<div className={styles.Controls}>
<Pagination.PrevTrigger className={styles.Trigger}>
<ChevronLeftIcon />
</Pagination.PrevTrigger>
{pagination.pages.map((page, index) =>
page.type === 'page' ? (
<Pagination.Item key={index} {...page} className={styles.Item}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis key={index} index={index} className={styles.Ellipsis}>
…
</Pagination.Ellipsis>
),
)}
<Pagination.NextTrigger className={styles.Trigger}>
<ChevronRightIcon />
</Pagination.NextTrigger>
</div>
<div className="stack">
<p className={styles.Text}>
Showing {pagination.pageRange.start + 1}-{pagination.pageRange.end} of {pagination.count} results
</p>
<p className={styles.Text}>
Page {pagination.page} of {pagination.totalPages}
</p>
</div>
</>
)}
</Pagination.Context>
</Pagination.Root>
)
}
import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid'
import { Pagination } from '@ark-ui/solid/pagination'
import { For } from 'solid-js'
import styles from 'styles/pagination.module.css'
export const PageRange = () => {
return (
<Pagination.Root count={100} pageSize={10} class={styles.Root}>
<Pagination.Context>
{(pagination) => (
<>
<div class={styles.Controls}>
<Pagination.PrevTrigger class={styles.Trigger}>
<ChevronLeftIcon />
</Pagination.PrevTrigger>
<For each={pagination().pages}>
{(page, index) =>
page.type === 'page' ? (
<Pagination.Item {...page} class={styles.Item}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis index={index()} class={styles.Ellipsis}>
…
</Pagination.Ellipsis>
)
}
</For>
<Pagination.NextTrigger class={styles.Trigger}>
<ChevronRightIcon />
</Pagination.NextTrigger>
</div>
<div class="stack">
<p class={styles.Text}>
Showing {pagination().pageRange.start + 1}-{pagination().pageRange.end} of {pagination().count} results
</p>
<p class={styles.Text}>
Page {pagination().page} of {pagination().totalPages}
</p>
</div>
</>
)}
</Pagination.Context>
</Pagination.Root>
)
}
<script setup lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
import { Pagination } from '@ark-ui/vue/pagination'
import styles from 'styles/pagination.module.css'
</script>
<template>
<Pagination.Root :count="100" :page-size="10" :class="styles.Root">
<Pagination.Context v-slot="pagination">
<div :class="styles.Controls">
<Pagination.PrevTrigger :class="styles.Trigger">
<ChevronLeft />
</Pagination.PrevTrigger>
<template v-for="(page, index) in pagination.pages" :key="index">
<Pagination.Item v-if="page.type === 'page'" v-bind="page" :class="styles.Item">
{{ page.value }}
</Pagination.Item>
<Pagination.Ellipsis v-else :index="index" :class="styles.Ellipsis">…</Pagination.Ellipsis>
</template>
<Pagination.NextTrigger :class="styles.Trigger">
<ChevronRight />
</Pagination.NextTrigger>
</div>
<div class="stack">
<p :class="styles.Text">
Showing {{ pagination.pageRange.start + 1 }}-{{ pagination.pageRange.end }} of {{ pagination.count }} results
</p>
<p :class="styles.Text">Page {{ pagination.page }} of {{ pagination.totalPages }}</p>
</div>
</Pagination.Context>
</Pagination.Root>
</template>
<script lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-svelte'
import { Pagination } from '@ark-ui/svelte/pagination'
import styles from 'styles/pagination.module.css'
</script>
<Pagination.Root count={100} pageSize={10} class={styles.Root}>
<Pagination.Context>
{#snippet render(pagination)}
<div class={styles.Controls}>
<Pagination.PrevTrigger class={styles.Trigger}>
<ChevronLeft />
</Pagination.PrevTrigger>
{#each pagination().pages as page, index}
{#if page.type === 'page'}
<Pagination.Item {...page} class={styles.Item}>{page.value}</Pagination.Item>
{:else}
<Pagination.Ellipsis {index} class={styles.Ellipsis}>…</Pagination.Ellipsis>
{/if}
{/each}
<Pagination.NextTrigger class={styles.Trigger}>
<ChevronRight />
</Pagination.NextTrigger>
</div>
<div class="stack">
<p class={styles.Text}>
Showing {pagination().pageRange.start + 1}-{pagination().pageRange.end} of {pagination()
.count} results
</p>
<p class={styles.Text}>
Page {pagination().page} of {pagination().totalPages}
</p>
</div>
{/snippet}
</Pagination.Context>
</Pagination.Root>
Page Size Control
Control the number of items per page dynamically using setPageSize(). This example shows how to integrate a native
select element to change the page size.
Note: For uncontrolled behavior, use
defaultPageSizeto set the initial value. For controlled behavior, usepageSizeandonPageSizeChangeto programmatically manage the page size.
import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'
import { Pagination } from '@ark-ui/react/pagination'
import styles from 'styles/pagination.module.css'
export const PageSizeControl = () => {
return (
<Pagination.Root count={100} defaultPageSize={10} className={styles.Root}>
<Pagination.Context>
{(pagination) => (
<>
<div className="hstack">
<label className={styles.Text}>Items per page:</label>
<select
className={styles.PageSizeSelect}
value={pagination.pageSize}
onChange={(e) => pagination.setPageSize(Number(e.target.value))}
>
<option value={5}>5</option>
<option value={10}>10</option>
<option value={20}>20</option>
<option value={50}>50</option>
</select>
</div>
<div className={styles.Controls}>
<Pagination.PrevTrigger className={styles.Trigger}>
<ChevronLeftIcon />
</Pagination.PrevTrigger>
{pagination.pages.map((page, index) =>
page.type === 'page' ? (
<Pagination.Item key={index} {...page} className={styles.Item}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis key={index} index={index} className={styles.Ellipsis}>
…
</Pagination.Ellipsis>
),
)}
<Pagination.NextTrigger className={styles.Trigger}>
<ChevronRightIcon />
</Pagination.NextTrigger>
</div>
<p className={styles.Text}>
Page {pagination.page} of {pagination.totalPages}
</p>
</>
)}
</Pagination.Context>
</Pagination.Root>
)
}
import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid'
import { Pagination } from '@ark-ui/solid/pagination'
import { For } from 'solid-js'
import styles from 'styles/pagination.module.css'
export const PageSizeControl = () => {
return (
<Pagination.Root count={100} defaultPageSize={10} class={styles.Root}>
<Pagination.Context>
{(pagination) => (
<>
<div class="hstack">
<label class={styles.Text}>Items per page:</label>
<select
class={styles.PageSizeSelect}
value={pagination().pageSize}
onChange={(e) => pagination().setPageSize(Number(e.target.value))}
>
<option value={5}>5</option>
<option value={10}>10</option>
<option value={20}>20</option>
<option value={50}>50</option>
</select>
</div>
<div class={styles.Controls}>
<Pagination.PrevTrigger class={styles.Trigger}>
<ChevronLeftIcon />
</Pagination.PrevTrigger>
<For each={pagination().pages}>
{(page, index) =>
page.type === 'page' ? (
<Pagination.Item {...page} class={styles.Item}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis index={index()} class={styles.Ellipsis}>
…
</Pagination.Ellipsis>
)
}
</For>
<Pagination.NextTrigger class={styles.Trigger}>
<ChevronRightIcon />
</Pagination.NextTrigger>
</div>
<p class={styles.Text}>
Page {pagination().page} of {pagination().totalPages}
</p>
</>
)}
</Pagination.Context>
</Pagination.Root>
)
}
<script setup lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
import { Pagination } from '@ark-ui/vue/pagination'
import styles from 'styles/pagination.module.css'
</script>
<template>
<Pagination.Root :count="100" :default-page-size="10" :class="styles.Root">
<Pagination.Context v-slot="pagination">
<div class="hstack">
<label :class="styles.Text">Items per page:</label>
<select
:class="styles.PageSizeSelect"
:value="pagination.pageSize"
@change="(event) => pagination.setPageSize(Number((event.currentTarget as HTMLSelectElement).value))"
>
<option :value="5">5</option>
<option :value="10">10</option>
<option :value="20">20</option>
<option :value="50">50</option>
</select>
</div>
<div :class="styles.Controls">
<Pagination.PrevTrigger :class="styles.Trigger">
<ChevronLeft />
</Pagination.PrevTrigger>
<template v-for="(page, index) in pagination.pages" :key="index">
<Pagination.Item v-if="page.type === 'page'" v-bind="page" :class="styles.Item">
{{ page.value }}
</Pagination.Item>
<Pagination.Ellipsis v-else :index="index" :class="styles.Ellipsis">…</Pagination.Ellipsis>
</template>
<Pagination.NextTrigger :class="styles.Trigger">
<ChevronRight />
</Pagination.NextTrigger>
</div>
<p :class="styles.Text">Page {{ pagination.page }} of {{ pagination.totalPages }}</p>
</Pagination.Context>
</Pagination.Root>
</template>
<script lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-svelte'
import { Pagination } from '@ark-ui/svelte/pagination'
import styles from 'styles/pagination.module.css'
</script>
<Pagination.Root count={100} defaultPageSize={10} class={styles.Root}>
<Pagination.Context>
{#snippet render(pagination)}
<div class="hstack">
<label class={styles.Text}>Items per page:</label>
<select
class={styles.PageSizeSelect}
value={pagination().pageSize}
onchange={(e) => pagination().setPageSize(Number(e.currentTarget.value))}
>
<option value={5}>5</option>
<option value={10}>10</option>
<option value={20}>20</option>
<option value={50}>50</option>
</select>
</div>
<div class={styles.Controls}>
<Pagination.PrevTrigger class={styles.Trigger}>
<ChevronLeft />
</Pagination.PrevTrigger>
{#each pagination().pages as page, index}
{#if page.type === 'page'}
<Pagination.Item {...page} class={styles.Item}>{page.value}</Pagination.Item>
{:else}
<Pagination.Ellipsis {index} class={styles.Ellipsis}>…</Pagination.Ellipsis>
{/if}
{/each}
<Pagination.NextTrigger class={styles.Trigger}>
<ChevronRight />
</Pagination.NextTrigger>
</div>
<p class={styles.Text}>
Page {pagination().page} of {pagination().totalPages}
</p>
{/snippet}
</Pagination.Context>
</Pagination.Root>
Link Pagination
Create pagination with link navigation for better SEO and accessibility. This example shows how to use the pagination component with anchor links instead of buttons.
import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'
import { Pagination, usePagination } from '@ark-ui/react/pagination'
import styles from 'styles/pagination.module.css'
export const Link = () => {
const pagination = usePagination({
type: 'link',
count: 100,
pageSize: 10,
siblingCount: 2,
getPageUrl: ({ page }) => `/page=${page}`,
})
return (
<Pagination.RootProvider value={pagination} className={styles.Root}>
<div className={styles.Controls}>
<a className={styles.Trigger} {...pagination.getPrevTriggerProps()}>
<ChevronLeftIcon />
</a>
{pagination.pages.map((page, index) =>
page.type === 'page' ? (
<a key={index} className={styles.Item} {...pagination.getItemProps(page)}>
{page.value}
</a>
) : (
<span key={index} className={styles.Ellipsis} {...pagination.getEllipsisProps({ index })}>
…
</span>
),
)}
<a className={styles.Trigger} {...pagination.getNextTriggerProps()}>
<ChevronRightIcon />
</a>
</div>
</Pagination.RootProvider>
)
}
import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid'
import { Pagination, usePagination } from '@ark-ui/solid/pagination'
import { For } from 'solid-js'
import styles from 'styles/pagination.module.css'
export const Link = () => {
const pagination = usePagination({
type: 'link',
count: 100,
pageSize: 10,
siblingCount: 2,
getPageUrl: ({ page }) => `/page=${page}`,
})
return (
<Pagination.RootProvider value={pagination} class={styles.Root}>
<div class={styles.Controls}>
<a class={styles.Trigger} {...pagination().getPrevTriggerProps()}>
<ChevronLeftIcon />
</a>
<For each={pagination().pages}>
{(page, index) =>
page.type === 'page' ? (
<a class={styles.Item} {...pagination().getItemProps(page)}>
{page.value}
</a>
) : (
<span class={styles.Ellipsis} {...pagination().getEllipsisProps({ index: index() })}>
…
</span>
)
}
</For>
<a class={styles.Trigger} {...pagination().getNextTriggerProps()}>
<ChevronRightIcon />
</a>
</div>
</Pagination.RootProvider>
)
}
<script setup lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
import { Pagination, usePagination } from '@ark-ui/vue/pagination'
import styles from 'styles/pagination.module.css'
const pagination = usePagination({
type: 'link',
count: 100,
pageSize: 10,
siblingCount: 2,
getPageUrl: ({ page }) => `/page=${page}`,
})
</script>
<template>
<Pagination.RootProvider :value="pagination" :class="styles.Root">
<div :class="styles.Controls">
<a :class="styles.Trigger" v-bind="pagination.getPrevTriggerProps()">
<ChevronLeft />
</a>
<template v-for="(page, index) in pagination.pages" :key="index">
<a v-if="page.type === 'page'" :class="styles.Item" v-bind="pagination.getItemProps(page)">
{{ page.value }}
</a>
<span v-else :class="styles.Ellipsis" v-bind="pagination.getEllipsisProps({ index })">…</span>
</template>
<a :class="styles.Trigger" v-bind="pagination.getNextTriggerProps()">
<ChevronRight />
</a>
</div>
</Pagination.RootProvider>
</template>
<script lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-svelte'
import { Pagination, usePagination } from '@ark-ui/svelte/pagination'
import styles from 'styles/pagination.module.css'
const id = $props.id()
const pagination = usePagination({
id,
type: 'link',
count: 100,
pageSize: 10,
siblingCount: 2,
getPageUrl: ({ page }) => `/page=${page}`,
})
</script>
<Pagination.RootProvider value={pagination} class={styles.Root}>
<div class={styles.Controls}>
<a class={styles.Trigger} {...pagination().getPrevTriggerProps()}>
<ChevronLeft />
</a>
{#each pagination().pages as page, index (index)}
{#if page.type === 'page'}
<a class={styles.Item} {...pagination().getItemProps(page)}>{page.value}</a>
{:else}
<span class={styles.Ellipsis} {...pagination().getEllipsisProps({ index })}>…</span>
{/if}
{/each}
<a class={styles.Trigger} {...pagination().getNextTriggerProps()}>
<ChevronRight />
</a>
</div>
</Pagination.RootProvider>
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 { ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'
import { Pagination, usePagination } from '@ark-ui/react/pagination'
import styles from 'styles/pagination.module.css'
export const RootProvider = () => {
const pagination = usePagination({ count: 5000, pageSize: 10, siblingCount: 2 })
return (
<div className="stack">
<button className={styles.Trigger} onClick={() => pagination.goToNextPage()}>
Next Page
</button>
<Pagination.RootProvider value={pagination} className={styles.Root}>
<div className={styles.Controls}>
<Pagination.PrevTrigger className={styles.Trigger}>
<ChevronLeftIcon />
</Pagination.PrevTrigger>
<Pagination.Context>
{(pagination) =>
pagination.pages.map((page, index) =>
page.type === 'page' ? (
<Pagination.Item key={index} {...page} className={styles.Item}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis key={index} index={index} className={styles.Ellipsis}>
…
</Pagination.Ellipsis>
),
)
}
</Pagination.Context>
<Pagination.NextTrigger className={styles.Trigger}>
<ChevronRightIcon />
</Pagination.NextTrigger>
</div>
</Pagination.RootProvider>
</div>
)
}
import { ChevronLeftIcon, ChevronRightIcon } from 'lucide-solid'
import { Pagination, usePagination } from '@ark-ui/solid/pagination'
import { For } from 'solid-js'
import styles from 'styles/pagination.module.css'
export const RootProvider = () => {
const pagination = usePagination({ count: 5000, pageSize: 10, siblingCount: 2 })
return (
<div class="stack">
<button class={styles.Trigger} onClick={() => pagination().goToNextPage()}>
Next Page
</button>
<Pagination.RootProvider value={pagination} class={styles.Root}>
<div class={styles.Controls}>
<Pagination.PrevTrigger class={styles.Trigger}>
<ChevronLeftIcon />
</Pagination.PrevTrigger>
<Pagination.Context>
{(pagination) => (
<For each={pagination().pages}>
{(page, index) =>
page.type === 'page' ? (
<Pagination.Item {...page} class={styles.Item}>
{page.value}
</Pagination.Item>
) : (
<Pagination.Ellipsis index={index()} class={styles.Ellipsis}>
…
</Pagination.Ellipsis>
)
}
</For>
)}
</Pagination.Context>
<Pagination.NextTrigger class={styles.Trigger}>
<ChevronRightIcon />
</Pagination.NextTrigger>
</div>
</Pagination.RootProvider>
</div>
)
}
<script setup lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-vue-next'
import { Pagination, usePagination } from '@ark-ui/vue/pagination'
import styles from 'styles/pagination.module.css'
const pagination = usePagination({ count: 5000, pageSize: 10, siblingCount: 2 })
</script>
<template>
<div class="stack">
<button :class="styles.Trigger" @click="pagination.goToNextPage()">Next Page</button>
<Pagination.RootProvider :value="pagination" :class="styles.Root">
<div :class="styles.Controls">
<Pagination.PrevTrigger :class="styles.Trigger">
<ChevronLeft />
</Pagination.PrevTrigger>
<Pagination.Context v-slot="pagination">
<template v-for="(page, index) in pagination.pages" :key="index">
<Pagination.Item v-if="page.type === 'page'" v-bind="page" :class="styles.Item">
{{ page.value }}
</Pagination.Item>
<Pagination.Ellipsis v-else :index="index" :class="styles.Ellipsis">…</Pagination.Ellipsis>
</template>
</Pagination.Context>
<Pagination.NextTrigger :class="styles.Trigger">
<ChevronRight />
</Pagination.NextTrigger>
</div>
</Pagination.RootProvider>
</div>
</template>
<script lang="ts">
import { ChevronLeft, ChevronRight } from 'lucide-svelte'
import { Pagination, usePagination } from '@ark-ui/svelte/pagination'
import styles from 'styles/pagination.module.css'
const id = $props.id()
const pagination = usePagination({
id,
count: 5000,
pageSize: 10,
siblingCount: 2,
})
</script>
<div class="stack">
<button class={styles.Trigger} onclick={() => pagination().goToNextPage()}>Next Page</button>
<Pagination.RootProvider value={pagination} class={styles.Root}>
<div class={styles.Controls}>
<Pagination.PrevTrigger class={styles.Trigger}>
<ChevronLeft />
</Pagination.PrevTrigger>
{#each pagination().pages as page, index (index)}
{#if page.type === 'page'}
<Pagination.Item {...page} class={styles.Item}>
{page.value}
</Pagination.Item>
{:else}
<Pagination.Ellipsis {index} class={styles.Ellipsis}>…</Pagination.Ellipsis>
{/if}
{/each}
<Pagination.NextTrigger class={styles.Trigger}>
<ChevronRight />
</Pagination.NextTrigger>
</div>
</Pagination.RootProvider>
</div>
If you're using the
RootProvidercomponent, you don't need to use theRootcomponent.
API Reference
Props
Root
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
count | numberTotal number of data items | |
defaultPage | 1 | numberThe initial active page when rendered. Use when you don't need to control the active page of the pagination. |
defaultPageSize | 10 | numberThe initial number of data items per page when rendered. Use when you don't need to control the page size of the pagination. |
getPageUrl | (details: PageUrlDetails) => stringFunction to generate href attributes for pagination links. Only used when `type` is set to "link". | |
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) => voidCalled when the page number is changed | |
onPageSizeChange | (details: PageSizeChangeDetails) => voidCalled when the page size is changed | |
page | numberThe controlled active page | |
pageSize | numberThe controlled number of data items per page | |
siblingCount | 1 | numberNumber of pages to show beside active page |
translations | IntlTranslationsSpecifies the localized strings that identifies the accessibility elements and their states | |
type | 'button' | 'button' | 'link'The type of the trigger element |
Ellipsis
| Prop | Default | Type |
|---|---|---|
index | number | |
asChild | booleanUse 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 | booleanUse 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 | booleanUse 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 | booleanUse 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 | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Context
These are the properties available when using Pagination.Context, usePaginationContext hook or usePagination hook.
API
| Property | Type |
|---|---|
page | numberThe current page. |
count | numberThe total number of data items. |
pageSize | numberThe number of data items per page. |
totalPages | numberThe total number of pages. |
pages | PagesThe page range. Represented as an array of page numbers (including ellipsis) |
previousPage | numberThe previous page. |
nextPage | numberThe next page. |
pageRange | PageRangeThe page range. Represented as an object with `start` and `end` properties. |
slice | <V>(data: V[]) => V[]Function to slice an array of data based on the current page. |
setPageSize | (size: number) => voidFunction to set the page size. |
setPage | (page: number) => voidFunction to set the current page. |
goToNextPage | VoidFunctionFunction to go to the next page. |
goToPrevPage | VoidFunctionFunction to go to the previous page. |
goToFirstPage | VoidFunctionFunction to go to the first page. |
goToLastPage | VoidFunctionFunction to go to the last page. |