Skip to main content

Pagination lets users navigate data split across multiple pages.

Loading...

Installation

Install the pagination package:

npm install @zag-js/pagination @zag-js/vue # or yarn add @zag-js/pagination @zag-js/vue

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-part attribute to help identify them in the DOM.

Usage

Import the pagination package:

import * as pagination from "@zag-js/pagination"

The pagination package exports two key functions:

  • machine - State machine logic.
  • connect - Maps machine state to JSX props and event handlers.

Pass a unique id to useMachine so generated element ids stay predictable.

<script setup> import * as pagination from "@zag-js/pagination" import { normalizeProps, useMachine } from "@zag-js/vue" import { computed } from "vue" import { data } from "./data" const service = useMachine(pagination.machine, { id: "1", count: data.length, }) const api = computed(() => pagination.connect(service, normalizeProps)) </script> <template> <nav v-if="api.totalPages > 1" v-bind="api.getRootProps()"> <ul> <li> <a href="#previous" v-bind="api.getPrevTriggerProps()"> Previous <span class="visually-hidden">Page</span> </a> </li> <li v-for="(page, i) in api.pages" :key="page.type === 'page' ? page.value : `ellipsis-${i}`" > <span v-if="page.type === 'page'"> <a :href="`#${page.value}`" v-bind="api.getItemProps(page)"> {{page.value}} </a></span > <span v-else> <span v-bind="api.getEllipsisProps({ index: i })">&#8230;</span> </span> </li> <li> <a href="#next" v-bind="api.getNextTriggerProps()"> Next <span class="visually-hidden">Page</span> </a> </li> </ul> </nav> </template>
const api = pagination.connect(service) // You can slice the data, to get data for current page const currentPageData = data.slice(api.pageRange.start, api.pageRange.end) api.page // => 1 api.setPage(3) // page => 3 api.previousPage // => 2 api.nextPage // => 4 api.pages /* [ { "type": "page", "value": 1, }, { "type": "page", "value": 2, }, { "type": "ellipsis", }, { "type": "page", "value": 3, }, { "type": "page", "value": 4, }, ] */ api.pageRange // => { start: 4, end: 13 }

Controlled page

Use page and onPageChange to control the current page externally.

const service = useMachine(pagination.machine, { count: 500, pageSize: 20, page, onPageChange(details) { setPage(details.page) }, })

Controlled page size

Use pageSize and onPageSizeChange to control page size.

const service = useMachine(pagination.machine, { count: 500, pageSize, onPageSizeChange(details) { setPageSize(details.pageSize) }, })

Initial page and page size

Use defaultPage and defaultPageSize for uncontrolled initial values.

const service = useMachine(pagination.machine, { count: 500, defaultPage: 3, defaultPageSize: 20, })

Set type: "link" and provide getPageUrl to render real navigation links.

const service = useMachine(pagination.machine, { count: 500, type: "link", getPageUrl(details) { return `/products?page=${details.page}&pageSize=${details.pageSize}` }, })

Customizing visible page ranges

Use siblingCount and boundaryCount to control how many page items are shown.

const service = useMachine(pagination.machine, { count: 500, siblingCount: 2, boundaryCount: 2, })

Customizing accessibility labels

Use translations to customize trigger and page labels.

const service = useMachine(pagination.machine, { count: 500, translations: { rootLabel: "Results pages", prevTriggerLabel: "Previous page", nextTriggerLabel: "Next page", itemLabel: ({ page, totalPages }) => `Page ${page} of ${totalPages}`, }, })

Styling guide

Each part includes a data-part attribute you can target in CSS.

[data-part="root"] { /* styles for the pagination's root */ } [data-part="item"] { /* styles for the pagination's items */ } [data-part="ellipsis"] { /* styles for the pagination's ellipsis */ } [data-part="prev-trigger"] { /* styles for the pagination's previous page trigger */ } [data-part="next-trigger"] { /* styles for the pagination's next page trigger */ } /* We add a data-disabled attribute to the prev/next items when on the first/last page */ [data-part="prev-trigger"][data-disabled] { /* styles for the pagination's previous page trigger when on first page */ } [data-part="next-trigger"][data-disabled] { /* styles for the pagination's next page trigger when on first page */ }

Methods and Properties

Machine Context

The pagination machine exposes the following context properties:

  • idsPartial<{ root: string; ellipsis: (index: number) => string; firstTrigger: string; prevTrigger: string; nextTrigger: string; lastTrigger: string; item: (page: number) => string; }>The ids of the elements in the accordion. Useful for composition.
  • translationsIntlTranslationsSpecifies the localized strings that identifies the accessibility elements and their states
  • countnumberTotal number of data items
  • pageSizenumberThe controlled number of data items per page
  • defaultPageSizenumberThe initial number of data items per page when rendered. Use when you don't need to control the page size of the pagination.
  • siblingCountnumberNumber of pages to show beside active page
  • boundaryCountnumberNumber of pages to show at the beginning and end
  • pagenumberThe controlled active page
  • defaultPagenumberThe initial active page when rendered. Use when you don't need to control the active page of the pagination.
  • onPageChange(details: PageChangeDetails) => voidCalled when the page number is changed
  • onPageSizeChange(details: PageSizeChangeDetails) => voidCalled when the page size is changed
  • type"button" | "link"The type of the trigger element
  • getPageUrl(details: PageUrlDetails) => stringFunction to generate href attributes for pagination links. Only used when `type` is set to "link".
  • dir"ltr" | "rtl"The document's text/writing direction.
  • idstringThe unique identifier of the machine.
  • getRootNode() => ShadowRoot | Node | DocumentA root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.

Machine API

The pagination api exposes the following methods:

  • pagenumberThe current page.
  • countnumberThe total number of data items.
  • pageSizenumberThe number of data items per page.
  • totalPagesnumberThe total number of pages.
  • pagesPagesThe page range. Represented as an array of page numbers (including ellipsis)
  • previousPagenumberThe previous page.
  • nextPagenumberThe next page.
  • pageRangePageRangeThe 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.
  • goToNextPageVoidFunctionFunction to go to the next page.
  • goToPrevPageVoidFunctionFunction to go to the previous page.
  • goToFirstPageVoidFunctionFunction to go to the first page.
  • goToLastPageVoidFunctionFunction to go to the last page.

Data Attributes

Item
data-scope
pagination
data-part
item
data-index
The index of the item
data-selected
Present when selected
PrevTrigger
data-scope
pagination
data-part
prev-trigger
data-disabled
Present when disabled
FirstTrigger
data-scope
pagination
data-part
first-trigger
data-disabled
Present when disabled
NextTrigger
data-scope
pagination
data-part
next-trigger
data-disabled
Present when disabled
LastTrigger
data-scope
pagination
data-part
last-trigger
data-disabled
Present when disabled
Edit this page on GitHub