{"slug":"pagination","title":"Pagination","description":"Using the pagination machine in your project.","contentType":"component","framework":"react","content":"Pagination lets users navigate data split across multiple pages.\n\n## Resources\n\n\n[Latest version: v1.35.3](https://www.npmjs.com/package/@zag-js/pagination)\n[Logic Visualizer](https://zag-visualizer.vercel.app/pagination)\n[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/pagination)\n\n\n\n## Installation\n\nInstall the pagination package:\n\n```bash\nnpm install @zag-js/pagination @zag-js/react\n# or\nyarn add @zag-js/pagination @zag-js/react\n```\n\n## Anatomy\n\nTo set up the pagination correctly, you'll need to understand its anatomy and\nhow we name its parts.\n\n> Each part includes a `data-part` attribute to help identify them in the DOM.\n\n\n\n## Usage\n\nImport the pagination package:\n\n```jsx\nimport * as pagination from \"@zag-js/pagination\"\n```\n\nThe pagination package exports two key functions:\n\n- `machine` - State machine logic.\n- `connect` - Maps machine state to JSX props and event handlers.\n\n> Pass a unique `id` to `useMachine` so generated element ids stay predictable.\n\n```jsx\nimport * as pagination from \"@zag-js/pagination\"\nimport { useMachine, normalizeProps } from \"@zag-js/react\"\nimport { data } from \"./data\"\n\nfunction Pagination() {\n  const service = useMachine(pagination.machine, {\n    id: \"1\",\n    count: data.length,\n  })\n\n  const api = pagination.connect(service, normalizeProps)\n\n  return (\n    <div>\n      {api.totalPages > 1 && (\n        <nav {...api.getRootProps()}>\n          <ul>\n            <li>\n              <a href=\"#previous\" {...api.getPrevTriggerProps()}>\n                Previous <span className=\"visually-hidden\">Page</span>\n              </a>\n            </li>\n            {api.pages.map((page, i) => {\n              if (page.type === \"page\")\n                return (\n                  <li key={page.value}>\n                    <a href={`#${page.value}`} {...api.getItemProps(page)}>\n                      {page.value}\n                    </a>\n                  </li>\n                )\n              else\n                return (\n                  <li key={`ellipsis-${i}`}>\n                    <span {...api.getEllipsisProps({ index: i })}>&#8230;</span>\n                  </li>\n                )\n            })}\n            <li>\n              <a href=\"#next\" {...api.getNextTriggerProps()}>\n                Next <span className=\"visually-hidden\">Page</span>\n              </a>\n            </li>\n          </ul>\n        </nav>\n      )}\n    </div>\n  )\n}\n```\n\n```jsx\nconst api = pagination.connect(service)\n\n// You can slice the data, to get data for current page\nconst currentPageData = data.slice(api.pageRange.start, api.pageRange.end)\n\napi.page\n// => 1\n\napi.setPage(3)\n// page => 3\n\napi.previousPage\n// => 2\n\napi.nextPage\n// => 4\n\napi.pages\n/*\n    [\n      {\n        \"type\": \"page\",\n        \"value\": 1,\n      },\n      {\n        \"type\": \"page\",\n        \"value\": 2,\n      },\n      {\n        \"type\": \"ellipsis\",\n      },\n      {\n        \"type\": \"page\",\n        \"value\": 3,\n      },\n      {\n        \"type\": \"page\",\n        \"value\": 4,\n      },\n    ]\n*/\n\napi.pageRange\n// => { start: 4, end: 13 }\n```\n\n### Controlled page\n\nUse `page` and `onPageChange` to control the current page externally.\n\n```jsx\nconst service = useMachine(pagination.machine, {\n  count: 500,\n  pageSize: 20,\n  page,\n  onPageChange(details) {\n    setPage(details.page)\n  },\n})\n```\n\n### Controlled page size\n\nUse `pageSize` and `onPageSizeChange` to control page size.\n\n```jsx\nconst service = useMachine(pagination.machine, {\n  count: 500,\n  pageSize,\n  onPageSizeChange(details) {\n    setPageSize(details.pageSize)\n  },\n})\n```\n\n### Initial page and page size\n\nUse `defaultPage` and `defaultPageSize` for uncontrolled initial values.\n\n```jsx\nconst service = useMachine(pagination.machine, {\n  count: 500,\n  defaultPage: 3,\n  defaultPageSize: 20,\n})\n```\n\n### Link-based pagination\n\nSet `type: \"link\"` and provide `getPageUrl` to render real navigation links.\n\n```jsx\nconst service = useMachine(pagination.machine, {\n  count: 500,\n  type: \"link\",\n  getPageUrl(details) {\n    return `/products?page=${details.page}&pageSize=${details.pageSize}`\n  },\n})\n```\n\n### Customizing visible page ranges\n\nUse `siblingCount` and `boundaryCount` to control how many page items are shown.\n\n```jsx\nconst service = useMachine(pagination.machine, {\n  count: 500,\n  siblingCount: 2,\n  boundaryCount: 2,\n})\n```\n\n### Customizing accessibility labels\n\nUse `translations` to customize trigger and page labels.\n\n```jsx\nconst service = useMachine(pagination.machine, {\n  count: 500,\n  translations: {\n    rootLabel: \"Results pages\",\n    prevTriggerLabel: \"Previous page\",\n    nextTriggerLabel: \"Next page\",\n    itemLabel: ({ page, totalPages }) => `Page ${page} of ${totalPages}`,\n  },\n})\n```\n\n## Styling guide\n\nEach part includes a `data-part` attribute you can target in CSS.\n\n```css\n[data-part=\"root\"] {\n  /* styles for the pagination's root */\n}\n\n[data-part=\"item\"] {\n  /* styles for the pagination's items */\n}\n\n[data-part=\"ellipsis\"] {\n  /* styles for the pagination's ellipsis */\n}\n\n[data-part=\"prev-trigger\"] {\n  /* styles for the pagination's previous page trigger */\n}\n\n[data-part=\"next-trigger\"] {\n  /* styles for the pagination's next page trigger */\n}\n\n/* We add a data-disabled attribute to the prev/next items when on the first/last page  */\n\n[data-part=\"prev-trigger\"][data-disabled] {\n  /* styles for the pagination's previous page trigger when on first page */\n}\n\n[data-part=\"next-trigger\"][data-disabled] {\n  /* styles for the pagination's next page trigger when on first page */\n}\n```\n\n## Methods and Properties\n\n### Machine Context\n\nThe pagination machine exposes the following context properties:\n\n**`ids`**\nType: `Partial<{ root: string; ellipsis: (index: number) => string; firstTrigger: string; prevTrigger: string; nextTrigger: string; lastTrigger: string; item: (page: number) => string; }>`\nDescription: The ids of the elements in the accordion. Useful for composition.\n\n**`translations`**\nType: `IntlTranslations`\nDescription: Specifies the localized strings that identifies the accessibility elements and their states\n\n**`count`**\nType: `number`\nDescription: Total number of data items\n\n**`pageSize`**\nType: `number`\nDescription: The controlled number of data items per page\n\n**`defaultPageSize`**\nType: `number`\nDescription: The initial number of data items per page when rendered.\nUse when you don't need to control the page size of the pagination.\n\n**`siblingCount`**\nType: `number`\nDescription: Number of pages to show beside active page\n\n**`boundaryCount`**\nType: `number`\nDescription: Number of pages to show at the beginning and end\n\n**`page`**\nType: `number`\nDescription: The controlled active page\n\n**`defaultPage`**\nType: `number`\nDescription: The initial active page when rendered.\nUse when you don't need to control the active page of the pagination.\n\n**`onPageChange`**\nType: `(details: PageChangeDetails) => void`\nDescription: Called when the page number is changed\n\n**`onPageSizeChange`**\nType: `(details: PageSizeChangeDetails) => void`\nDescription: Called when the page size is changed\n\n**`type`**\nType: `\"button\" | \"link\"`\nDescription: The type of the trigger element\n\n**`getPageUrl`**\nType: `(details: PageUrlDetails) => string`\nDescription: Function to generate href attributes for pagination links.\nOnly used when `type` is set to \"link\".\n\n**`dir`**\nType: `\"ltr\" | \"rtl\"`\nDescription: The document's text/writing direction.\n\n**`id`**\nType: `string`\nDescription: The unique identifier of the machine.\n\n**`getRootNode`**\nType: `() => ShadowRoot | Node | Document`\nDescription: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.\n\n### Machine API\n\nThe pagination `api` exposes the following methods:\n\n**`page`**\nType: `number`\nDescription: The current page.\n\n**`count`**\nType: `number`\nDescription: The total number of data items.\n\n**`pageSize`**\nType: `number`\nDescription: The number of data items per page.\n\n**`totalPages`**\nType: `number`\nDescription: The total number of pages.\n\n**`pages`**\nType: `Pages`\nDescription: The page range. Represented as an array of page numbers (including ellipsis)\n\n**`previousPage`**\nType: `number`\nDescription: The previous page.\n\n**`nextPage`**\nType: `number`\nDescription: The next page.\n\n**`pageRange`**\nType: `PageRange`\nDescription: The page range. Represented as an object with `start` and `end` properties.\n\n**`slice`**\nType: `<V>(data: V[]) => V[]`\nDescription: Function to slice an array of data based on the current page.\n\n**`setPageSize`**\nType: `(size: number) => void`\nDescription: Function to set the page size.\n\n**`setPage`**\nType: `(page: number) => void`\nDescription: Function to set the current page.\n\n**`goToNextPage`**\nType: `VoidFunction`\nDescription: Function to go to the next page.\n\n**`goToPrevPage`**\nType: `VoidFunction`\nDescription: Function to go to the previous page.\n\n**`goToFirstPage`**\nType: `VoidFunction`\nDescription: Function to go to the first page.\n\n**`goToLastPage`**\nType: `VoidFunction`\nDescription: Function to go to the last page.\n\n### Data Attributes\n\n**`Item`**\n\n**`data-scope`**: pagination\n**`data-part`**: item\n**`data-index`**: The index of the item\n**`data-selected`**: Present when selected\n\n**`PrevTrigger`**\n\n**`data-scope`**: pagination\n**`data-part`**: prev-trigger\n**`data-disabled`**: Present when disabled\n\n**`FirstTrigger`**\n\n**`data-scope`**: pagination\n**`data-part`**: first-trigger\n**`data-disabled`**: Present when disabled\n\n**`NextTrigger`**\n\n**`data-scope`**: pagination\n**`data-part`**: next-trigger\n**`data-disabled`**: Present when disabled\n\n**`LastTrigger`**\n\n**`data-scope`**: pagination\n**`data-part`**: last-trigger\n**`data-disabled`**: Present when disabled","package":"@zag-js/pagination","editUrl":"https://github.com/chakra-ui/zag/edit/main/website/data/components/pagination.mdx"}