Skip to content

Pagination

Displays data in paged format and provides navigation between pages.
vue
<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">
          &#8230;
        </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.

bash
npm install radix-vue

Anatomy

Import all parts and piece them together.

vue
<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">
          &#8230;
        </PaginationEllipsis>
      </template>
      <PaginationNext />
      <PaginationLast />
    </PaginationList>
  </PaginationRoot>
</template>

API Reference

Root

Contains all of the paginations parts.

PropDefaultType
page
number

The controlled value of the current page. Can be binded with v-model.

defaultPage
1
number

The default page value

total
10
number

Number of items in your list

itemsPerPage
10
number

How many items per page

siblingCount
3
number

How many sibling should be shown around the current page

showEdges
boolean

true if it should always show first page, last page, and ellipsis

EmitType
@update:page
(value: number) => void

List

Used to show the list of pages. It also makes pagination accessible to assistive technologies.

PropDefaultType
as
div
string | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
false
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

Item

Used to render the button that changes the current page.

PropDefaultType
value
number

Value for the page

as
button
string | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
false
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

Data AttributeValue
[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.

PropDefaultType
as
div
string | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
false
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior.

Read our Composition guide for more details.

Data AttributeValue
[data-type]"ellipsis"

First

Triggers that set the page value to 1

PropDefaultType
as
button
string | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
false
boolean

Change 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

PropDefaultType
as
button
string | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
false
boolean

Change 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

PropDefaultType
as
button
string | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
false
boolean

Change 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

PropDefaultType
as
button
string | Component

The element or component this component should render as. Can be overwrite by asChild

asChild
false
boolean

Change 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.

vue
<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">
          &#8230;
        </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.

vue
<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.

vue
<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

KeyDescription
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