Pagination
Page navigation with composable page links, previous/next buttons, and ellipsis indicators.
Import
ts
import {
Pagination,
PaginationContent,
PaginationEllipsis,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationNextIcon,
PaginationPrevious,
PaginationPreviousIcon,
PaginationSummary,
} from '@heroui-vue/vue'Usage
<template>
<Pagination class="justify-center">
<PaginationContent>
<PaginationItem>
<PaginationPrevious :is-disabled="page === 1" @press="page -= 1">
<PaginationPreviousIcon />
<span>Previous</span>
</PaginationPrevious>
</PaginationItem>
<PaginationItem v-for="item in totalPages" :key="item">
<PaginationLink :is-active="item === page" @press="page = item">
{{ item }}
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationNext :is-disabled="page === totalPages" @press="page += 1">
<span>Next</span>
<PaginationNextIcon />
</PaginationNext>
</PaginationItem>
</PaginationContent>
</Pagination>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationNextIcon,
PaginationPrevious,
PaginationPreviousIcon,
} from '@heroui-vue/vue'
const page = ref(1)
const totalPages = 3
</script>Anatomy
vue
<Pagination>
<PaginationSummary>Showing 1-10 of 100 results</PaginationSummary>
<PaginationContent>
<PaginationItem>
<PaginationPrevious>
<PaginationPreviousIcon />
<span>Previous</span>
</PaginationPrevious>
</PaginationItem>
<PaginationItem>
<PaginationLink active>1</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationEllipsis />
</PaginationItem>
<PaginationItem>
<PaginationNext>
<span>Next</span>
<PaginationNextIcon />
</PaginationNext>
</PaginationItem>
</PaginationContent>
</Pagination>Sizes
sm
md
lg
<template>
<div class="flex flex-col gap-6">
<div v-for="size in sizes" :key="size" class="flex flex-col gap-2">
<span class="text-xs font-medium text-muted capitalize">{{ size }}</span>
<Pagination class="justify-center" :size="size">
<PaginationContent>
<PaginationItem>
<PaginationPrevious :is-disabled="pages[size] === 1" @press="pages[size] -= 1">
<PaginationPreviousIcon />
<span>Previous</span>
</PaginationPrevious>
</PaginationItem>
<PaginationItem v-for="item in totalPages" :key="item">
<PaginationLink :is-active="item === pages[size]" @press="pages[size] = item">
{{ item }}
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationNext :is-disabled="pages[size] === totalPages" @press="pages[size] += 1">
<span>Next</span>
<PaginationNextIcon />
</PaginationNext>
</PaginationItem>
</PaginationContent>
</Pagination>
</div>
</div>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationNextIcon,
PaginationPrevious,
PaginationPreviousIcon,
} from '@heroui-vue/vue'
const sizes = ['sm', 'md', 'lg'] as const
const totalPages = 3
const pages = reactive({ sm: 1, md: 1, lg: 1 })
</script>With Ellipsis
<template>
<div class="w-full max-w-2xs overflow-x-auto sm:max-w-full">
<Pagination class="justify-center">
<PaginationContent>
<PaginationItem>
<PaginationPrevious :is-disabled="page === 1" @press="page -= 1">
<PaginationPreviousIcon />
<span>Previous</span>
</PaginationPrevious>
</PaginationItem>
<PaginationItem v-for="(item, index) in pageItems" :key="`${item}-${index}`">
<PaginationEllipsis v-if="item === 'ellipsis'" />
<PaginationLink v-else :is-active="item === page" @press="page = item">
{{ item }}
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationNext :is-disabled="page === totalPages" @press="page += 1">
<span>Next</span>
<PaginationNextIcon />
</PaginationNext>
</PaginationItem>
</PaginationContent>
</Pagination>
</div>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import {
Pagination,
PaginationContent,
PaginationEllipsis,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationNextIcon,
PaginationPrevious,
PaginationPreviousIcon,
} from '@heroui-vue/vue'
const page = ref(1)
const totalPages = 12
const pageItems = computed(() => {
const pages: Array<number | 'ellipsis'> = [1]
if (page.value > 3) pages.push('ellipsis')
const start = Math.max(2, page.value - 1)
const end = Math.min(totalPages - 1, page.value + 1)
for (let item = start; item <= end; item += 1) {
pages.push(item)
}
if (page.value < totalPages - 2) pages.push('ellipsis')
pages.push(totalPages)
return pages
})
</script>Simple (Previous / Next)
<template>
<Pagination class="w-full">
<PaginationSummary>
{{ startItem }} to {{ endItem }} of {{ totalItems }} invoices
</PaginationSummary>
<PaginationContent>
<PaginationItem>
<PaginationPrevious :is-disabled="page === 1" @press="page -= 1">
<PaginationPreviousIcon />
<span>Prev</span>
</PaginationPrevious>
</PaginationItem>
<PaginationItem>
<PaginationNext :is-disabled="page === totalPages" @press="page += 1">
<span>Next</span>
<PaginationNextIcon />
</PaginationNext>
</PaginationItem>
</PaginationContent>
</Pagination>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationNext,
PaginationNextIcon,
PaginationPrevious,
PaginationPreviousIcon,
PaginationSummary,
} from '@heroui-vue/vue'
const page = ref(1)
const totalPages = 10
const itemsPerPage = 5
const totalItems = 50
const startItem = computed(() => (page.value - 1) * itemsPerPage + 1)
const endItem = computed(() => Math.min(page.value * itemsPerPage, totalItems))
</script>With Summary
<template>
<Pagination class="w-full">
<PaginationSummary>
Showing {{ startItem }}-{{ endItem }} of {{ totalItems }} results
</PaginationSummary>
<PaginationContent>
<PaginationItem>
<PaginationPrevious :is-disabled="page === 1" @press="page -= 1">
<PaginationPreviousIcon />
<span>Previous</span>
</PaginationPrevious>
</PaginationItem>
<PaginationItem v-for="(item, index) in pageItems" :key="`${item}-${index}`">
<PaginationEllipsis v-if="item === 'ellipsis'" />
<PaginationLink v-else :is-active="item === page" @press="page = item">
{{ item }}
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationNext :is-disabled="page === totalPages" @press="page += 1">
<span>Next</span>
<PaginationNextIcon />
</PaginationNext>
</PaginationItem>
</PaginationContent>
</Pagination>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import {
Pagination,
PaginationContent,
PaginationEllipsis,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationNextIcon,
PaginationPrevious,
PaginationPreviousIcon,
PaginationSummary,
} from '@heroui-vue/vue'
const page = ref(1)
const totalPages = 12
const itemsPerPage = 10
const totalItems = 120
const startItem = computed(() => (page.value - 1) * itemsPerPage + 1)
const endItem = computed(() => Math.min(page.value * itemsPerPage, totalItems))
const pageItems = computed(() => {
const pages: Array<number | 'ellipsis'> = [1]
if (page.value > 3) pages.push('ellipsis')
for (let item = Math.max(2, page.value - 1); item <= Math.min(totalPages - 1, page.value + 1); item += 1) {
pages.push(item)
}
if (page.value < totalPages - 2) pages.push('ellipsis')
pages.push(totalPages)
return pages
})
</script>Custom Icons
<template>
<Pagination class="justify-center">
<PaginationContent>
<PaginationItem>
<PaginationPrevious :is-disabled="page === 1" @press="page -= 1">
<PaginationPreviousIcon>
<svg fill="none" viewBox="0 0 20 20">
<path d="M12.5 5 7.5 10l5 5M8 10h8" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" />
</svg>
</PaginationPreviousIcon>
<span>Back</span>
</PaginationPrevious>
</PaginationItem>
<PaginationItem v-for="item in totalPages" :key="item">
<PaginationLink :is-active="item === page" @press="page = item">
{{ item }}
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationNext :is-disabled="page === totalPages" @press="page += 1">
<span>Forward</span>
<PaginationNextIcon>
<svg fill="none" viewBox="0 0 20 20">
<path d="m7.5 5 5 5-5 5M12 10H4" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" />
</svg>
</PaginationNextIcon>
</PaginationNext>
</PaginationItem>
</PaginationContent>
</Pagination>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationNextIcon,
PaginationPrevious,
PaginationPreviousIcon,
} from '@heroui-vue/vue'
const page = ref(1)
const totalPages = 3
</script>Controlled
<template>
<Pagination>
<PaginationSummary>
Showing {{ startItem }}-{{ endItem }} of {{ totalItems }} results
</PaginationSummary>
<PaginationContent>
<PaginationItem>
<PaginationPrevious :is-disabled="page === 1" @press="page -= 1">
<PaginationPreviousIcon />
<span>Previous</span>
</PaginationPrevious>
</PaginationItem>
<PaginationItem v-for="(item, index) in pageItems" :key="`${item}-${index}`">
<PaginationEllipsis v-if="item === 'ellipsis'" />
<PaginationLink v-else :is-active="item === page" @press="page = item">
{{ item }}
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationNext :is-disabled="page === totalPages" @press="page += 1">
<span>Next</span>
<PaginationNextIcon />
</PaginationNext>
</PaginationItem>
</PaginationContent>
</Pagination>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import {
Pagination,
PaginationContent,
PaginationEllipsis,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationNextIcon,
PaginationPrevious,
PaginationPreviousIcon,
PaginationSummary,
} from '@heroui-vue/vue'
const page = ref(1)
const totalPages = 12
const itemsPerPage = 10
const totalItems = 120
const startItem = computed(() => (page.value - 1) * itemsPerPage + 1)
const endItem = computed(() => Math.min(page.value * itemsPerPage, totalItems))
const pageItems = computed(() => {
const pages: Array<number | 'ellipsis'> = []
if (totalPages <= 7) {
for (let item = 1; item <= totalPages; item += 1) pages.push(item)
return pages
}
pages.push(1)
if (page.value > 3) pages.push('ellipsis')
for (let item = Math.max(2, page.value - 1); item <= Math.min(totalPages - 1, page.value + 1); item += 1) {
pages.push(item)
}
if (page.value < totalPages - 2) pages.push('ellipsis')
pages.push(totalPages)
return pages
})
</script>Disabled
<template>
<Pagination class="justify-center">
<PaginationContent>
<PaginationItem>
<PaginationPrevious is-disabled @press="page -= 1">
<PaginationPreviousIcon />
<span>Previous</span>
</PaginationPrevious>
</PaginationItem>
<PaginationItem v-for="item in totalPages" :key="item">
<PaginationLink :is-active="item === page" @press="page = item">
{{ item }}
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationNext is-disabled @press="page += 1">
<span>Next</span>
<PaginationNextIcon />
</PaginationNext>
</PaginationItem>
</PaginationContent>
</Pagination>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import {
Pagination,
PaginationContent,
PaginationItem,
PaginationLink,
PaginationNext,
PaginationNextIcon,
PaginationPrevious,
PaginationPreviousIcon,
} from '@heroui-vue/vue'
const page = ref(1)
const totalPages = 3
</script>Related Components
API
| Prop | Type | Default | Description |
|---|---|---|---|
size | 'sm' | 'md' | 'lg' | 'md' | Size of pagination controls |
ariaLabel | string | 'Pagination' | Accessible label for the navigation |
PaginationLink, PaginationPrevious, and PaginationNext emit press with the click event.