Pagination
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import { PaginationEllipsis, PaginationFirst, PaginationLast, PaginationList, PaginationListItem, PaginationNext, PaginationPrev, PaginationRoot } from 'radix-vue'
</script>
<template>
<PaginationRoot
:total="100"
:sibling-count="1"
show-edges
:default-page="2"
>
<PaginationList
v-slot="{ items }"
class="flex items-center gap-1 text-white"
>
<PaginationFirst class="w-9 h-9 flex items-center justify-center disabled:opacity-50 focus-within:outline focus-within:outline-1 focus-within:outline-offset-1 rounded">
<Icon icon="radix-icons:double-arrow-left" />
</PaginationFirst>
<PaginationPrev class="w-9 h-9 flex items-center justify-center mr-4 disabled:opacity-50 focus-within:outline focus-within:outline-1 focus-within:outline-offset-1 rounded">
<Icon icon="radix-icons:chevron-left" />
</PaginationPrev>
<template v-for="(page, index) in items">
<PaginationListItem
v-if="page.type === 'page'"
:key="index"
class="w-9 h-9 border rounded data-[selected]:bg-white data-[selected]:text-blackA11 hover:bg-white/10 transition focus-within:outline focus-within:outline-1 focus-within:outline-offset-1"
:value="page.value"
>
{{ page.value }}
</PaginationListItem>
<PaginationEllipsis
v-else
:key="page.type"
:index="index"
class="w-9 h-9 flex items-center justify-center"
>
…
</PaginationEllipsis>
</template>
<PaginationNext class="w-9 h-9 flex items-center justify-center ml-4 disabled:opacity-50 focus-within:outline focus-within:outline-1 focus-within:outline-offset-1 rounded">
<Icon icon="radix-icons:chevron-right" />
</PaginationNext>
<PaginationLast class="w-9 h-9 flex items-center justify-center disabled:opacity-50 focus-within:outline focus-within:outline-1 focus-within:outline-offset-1 rounded">
<Icon icon="radix-icons:double-arrow-right" />
</PaginationLast>
</PaginationList>
</PaginationRoot>
</template>Features
- Enable quick access to first, or last page
- Enable to show edges constantly, or not
Installation
Install the component from your command line.
$ npm add radix-vueAnatomy
Import all parts and piece them together.
<script setup>
import { PaginationEllipsis, PaginationFirst, PaginationLast, PaginationList, PaginationListItem, PaginationNext, PaginationPrev, PaginationRoot } from 'radix-vue'
</script>
<template>
<PaginationRoot>
<PaginationList v-slot="{ items }">
<PaginationFirst />
<PaginationPrev />
<template v-for="(page, index) in items">
<PaginationListItem
v-if="page.type === 'page'"
:key="index"
/>
<PaginationEllipsis
v-else
:key="page.type"
:index="index"
>
…
</PaginationEllipsis>
</template>
<PaginationNext />
<PaginationLast />
</PaginationList>
</PaginationRoot>
</template>API Reference
Root
Contains all of the paginations parts.
| Prop | Default | Type |
|---|---|---|
as | 'nav' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. | |
defaultPage | 1 | numberThe value of the page that should be active when initially rendered. Use when you do not need to control the value state. |
disabled | booleanWhen | |
itemsPerPage | 10 | numberNumber of items per page |
page | numberThe controlled value of the current page. Can be binded as | |
showEdges | false | booleanWhen |
siblingCount | 2 | numberNumber of sibling should be shown around the current page |
total | 0 | numberNumber of items in your list |
| Emit | Payload |
|---|---|
update:page | [value: number]Event handler called when the page value changes |
| Slots (default) | Payload |
|---|---|
page | numberCurrent page state |
pageCount | numberNumber of pages |
List
Used to show the list of pages. It also makes pagination accessible to assistive technologies.
| Prop | Default | Type |
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
| Slots (default) | Payload |
|---|---|
items | { type: 'ellipsis'; } | { type: 'page'; value: number; }Pages item |
Item
Used to render the button that changes the current page.
| Data Attribute | Value |
|---|---|
[data-selected] | "true" | "" |
[data-type] | "page" |
Ellipsis
Placeholder element when the list is long, and only a small amount of siblingCount was set and showEdges was set to true.
| Prop | Default | Type |
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
| Data Attribute | Value |
|---|---|
[data-type] | "ellipsis" |
First
Triggers that set the page value to 1
| Prop | Default | Type |
|---|---|---|
as | 'button' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
Prev
Triggers that set the page value to the previous page
| Prop | Default | Type |
|---|---|---|
as | 'button' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
Next
Triggers that set the page value to the next page
| Prop | Default | Type |
|---|---|---|
as | 'button' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
Last
Triggers that set the page value to the last page
| Prop | Default | Type |
|---|---|---|
as | 'button' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by |
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details. |
Examples
With ellipsis
You can add PaginationEllipsis as a visual cue for more previous and after items.
<script setup lang="ts">
import { PaginationEllipsis, PaginationList, PaginationListItem, PaginationRoot } from 'radix-vue'
</script>
<template>
<PaginationRoot>
<PaginationList v-slot="{ items }">
<template v-for="(page, index) in items">
<PaginationListItem
v-if="page.type === 'page'"
:key="index"
/>
<PaginationEllipsis
v-else
:key="page.type"
:index="index"
>
…
</PaginationEllipsis>
</template>
</PaginationList>
</PaginationRoot>
</template>With first/last button
You can add PaginationFirst to allow user to navigate to first page, or PaginationLast to navigate to last page.
<script setup lang="ts">
import { PaginationFirst, PaginationLast, PaginationList, PaginationListItem, PaginationRoot } from 'radix-vue'
</script>
<template>
<PaginationRoot>
<PaginationList>
<PaginationFirst />
...
<PaginationLast />
</PaginationList>
</PaginationRoot>
</template>Control page programmatically
You can control the current page by passing it a reactive value.
<script setup lang="ts">
import { PaginationRoot } from 'radix-vue'
import { Select } from './custom-select'
import { ref } from 'vue'
const currentPage = ref(1)
</script>
<template>
<Select v-model="currentPage" />
<PaginationRoot v-model:page="currentPage">
...
</PaginationRoot>
</template>Keyboard Interactions
| Key | Description |
|---|---|
Tab | Moves focus to the next focusable element. |
Space |
When focus is on a any trigger, trigger selected page or arrow navigation
|
Enter |
When focus is on a any trigger, trigger selected page or arrow navigation
|