Pagination
Page-by-page navigation for lists, tables, and search results. The VdPagination component renders a numbered control from a few data attributes, automatically collapsing long ranges with ellipses and emitting a pagination:change event as the user navigates.
Basic
Current page: 1
<!-- Framework markup: the JS expands data-pagination into the list -->
<ul class="vd-pagination"
data-pagination
data-total-pages="5"
data-current-page="1"></ul>Sizes
<ul class="vd-pagination vd-pagination-sm" data-pagination data-total-pages="5"></ul>
<ul class="vd-pagination" data-pagination data-total-pages="5"></ul>
<ul class="vd-pagination vd-pagination-lg" data-pagination data-total-pages="5"></ul>Alignment
<ul class="vd-pagination" data-pagination data-total-pages="6"></ul>
<ul class="vd-pagination vd-pagination-center" data-pagination data-total-pages="6"></ul>
<ul class="vd-pagination vd-pagination-right" data-pagination data-total-pages="6"></ul>Large Sets with Ellipsis
With more than data-max-visible pages, the control always shows the first and last page plus a window around the current page, separated by “…”.
Current page: 10
<!-- Large sets collapse to first/last + a window around the current page -->
<ul class="vd-pagination"
data-pagination
data-total-pages="20"
data-current-page="10"
data-max-visible="7"></ul>Disabled
Add disabled to make the whole control non-interactive while data is loading.
API Reference
Usage
<script setup lang="ts">
import { VdPagination } from "@vanduo-oss/vd3";
const page = ref(1);
</script>
<template>
<VdPagination v-model="page" :total="20" :max-visible="7" />
</template>Data Attributes
| Attribute | Description | Default |
|---|---|---|
data-pagination | Activates the component on a .vd-pagination element | — |
data-total-pages | Total number of pages to render | 1 |
data-current-page | The initially active page | 1 |
data-max-visible | Maximum page links shown before collapsing to ellipses | 7 |
CSS Classes
| Class | Description |
|---|---|
.vd-pagination | Flex list container for the pagination items |
.vd-pagination-item | An individual page slot (wraps a link or ellipsis) |
.vd-pagination-link | The clickable anchor inside a page item |
.vd-pagination-item.active | The current page (filled primary colour) |
.vd-pagination-item.disabled | A non-interactive item (e.g. Previous on page 1) |
.vd-pagination-prev / .vd-pagination-next | The previous / next navigation items |
.vd-pagination-ellipsis | The “…” gap shown between distant page ranges |
.vd-pagination-sm / .vd-pagination-lg | Size modifiers on the container |
.vd-pagination-center / .vd-pagination-right | Alignment modifiers on the container |
Component API
| Prop / event | Description |
|---|---|
v-model (modelValue) | Two-way bound current page (number). |
:total | Total number of pages. |
:max-visible | Max page links before collapsing to ellipses (default 7). |
:size / :align / :disabled | 'sm'|'md'|'lg' size, 'left'|'center'|'right' align, and a disabled flag. |
@update:modelValue / pagination:change | Fired with the new page; a native pagination:change { page, totalPages } also bubbles. |
Events
| Event | Description |
|---|---|
pagination:change | Fired on the element when the page changes. event.detail contains { page, totalPages } |
Programmatic Control
import { ref } from 'vue';
const page = ref(1);
// Jump programmatically — set the v-model ref, no global API needed
page.value = 4;
// React to page changes with @update:modelValue on the component,
// e.g. <VdPagination v-model="page" @update:modelValue="onPage" />
function onPage(p) {
console.log('Now on page', p);
}Accessibility
- The control is wrapped in
<nav aria-label="Pagination"> - The active page link carries
aria-current="page" - Each page link has a descriptive
aria-label(e.g."Page 4") - Ellipses use
aria-hidden="true"so they are skipped by screen readers - Previous / Next become
.disabled(and non-interactive) at the range boundaries