# Pagination **Category**: react **URL**: https://www.heroui.com/docs/react/components/pagination **Source**: https://raw.githubusercontent.com/heroui-inc/heroui/refs/heads/v3/apps/docs/content/docs/react/components/(navigation)/pagination.mdx > Page navigation with composable page links, previous/next buttons, and ellipsis indicators *** ## Import ```tsx import { Pagination } from '@heroui/react'; ``` ### Usage ```tsx "use client"; import {Pagination} from "@heroui/react"; import {useState} from "react"; export function PaginationBasic() { const [page, setPage] = useState(1); const totalPages = 3; return ( setPage((p) => p - 1)}> Previous {Array.from({length: totalPages}, (_, i) => i + 1).map((p) => ( setPage(p)}> {p} ))} setPage((p) => p + 1)}> Next ); } ``` ### Anatomy Import the Pagination component and access all parts using dot notation. ```tsx import { Pagination } from '@heroui/react'; export default () => ( Showing 1-10 of 100 results Previous 1 10 Next ); ``` ### Sizes ```tsx "use client"; import {Pagination} from "@heroui/react"; import {useState} from "react"; function SizePagination({size}: {size: "sm" | "md" | "lg"}) { const [page, setPage] = useState(1); const totalPages = 3; return (
{size} setPage((p) => p - 1)}> Previous {Array.from({length: totalPages}, (_, i) => i + 1).map((p) => ( setPage(p)}> {p} ))} setPage((p) => p + 1)}> Next
); } export function PaginationSizes() { return (
{(["sm", "md", "lg"] as const).map((size) => ( ))}
); } ``` ### With Ellipsis ```tsx "use client"; import {Pagination} from "@heroui/react"; import {useState} from "react"; export function PaginationWithEllipsis() { const [page, setPage] = useState(1); const totalPages = 12; const getPageNumbers = () => { const pages: (number | "ellipsis")[] = []; pages.push(1); if (page > 3) { pages.push("ellipsis"); } const start = Math.max(2, page - 1); const end = Math.min(totalPages - 1, page + 1); for (let i = start; i <= end; i++) { pages.push(i); } if (page < totalPages - 2) { pages.push("ellipsis"); } pages.push(totalPages); return pages; }; return (
setPage((p) => p - 1)}> Previous {getPageNumbers().map((p, i) => p === "ellipsis" ? ( ) : ( setPage(p)}> {p} ), )} setPage((p) => p + 1)}> Next
); } ``` ### Simple (Previous / Next) ```tsx "use client"; import {Pagination} from "@heroui/react"; import {useState} from "react"; export function PaginationSimplePrevNext() { const [page, setPage] = useState(1); const totalPages = 10; const itemsPerPage = 5; const totalItems = 50; const startItem = (page - 1) * itemsPerPage + 1; const endItem = Math.min(page * itemsPerPage, totalItems); return ( {startItem} to {endItem} of {totalItems} invoices setPage((p) => p - 1)}> Prev setPage((p) => p + 1)}> Next ); } ``` ### With Summary ```tsx "use client"; import {Pagination} from "@heroui/react"; import {useState} from "react"; export function PaginationWithSummary() { const [page, setPage] = useState(1); const totalPages = 12; const itemsPerPage = 10; const totalItems = 120; const getPageNumbers = () => { const pages: (number | "ellipsis")[] = []; pages.push(1); if (page > 3) { pages.push("ellipsis"); } const start = Math.max(2, page - 1); const end = Math.min(totalPages - 1, page + 1); for (let i = start; i <= end; i++) { pages.push(i); } if (page < totalPages - 2) { pages.push("ellipsis"); } pages.push(totalPages); return pages; }; const startItem = (page - 1) * itemsPerPage + 1; const endItem = Math.min(page * itemsPerPage, totalItems); return ( Showing {startItem}-{endItem} of {totalItems} results setPage((p) => p - 1)}> Previous {getPageNumbers().map((p, i) => p === "ellipsis" ? ( ) : ( setPage(p)}> {p} ), )} setPage((p) => p + 1)}> Next ); } ``` ### Custom Icons You can replace the default chevron icons by passing custom children to `PreviousIcon` and `NextIcon`. ```tsx "use client"; import {Pagination} from "@heroui/react"; import {Icon} from "@iconify/react"; import {useState} from "react"; export function PaginationCustomIcons() { const [page, setPage] = useState(1); const totalPages = 3; return ( setPage((p) => p - 1)}> Back {Array.from({length: totalPages}, (_, i) => i + 1).map((p) => ( setPage(p)}> {p} ))} setPage((p) => p + 1)}> Forward ); } ``` ### Controlled ```tsx "use client"; import {Pagination} from "@heroui/react"; import {useState} from "react"; export function PaginationControlled() { const [page, setPage] = useState(1); const totalPages = 12; const itemsPerPage = 10; const totalItems = 120; const getPageNumbers = () => { const pages: (number | "ellipsis")[] = []; if (totalPages <= 7) { for (let i = 1; i <= totalPages; i++) { pages.push(i); } } else { pages.push(1); if (page > 3) { pages.push("ellipsis"); } const start = Math.max(2, page - 1); const end = Math.min(totalPages - 1, page + 1); for (let i = start; i <= end; i++) { pages.push(i); } if (page < totalPages - 2) { pages.push("ellipsis"); } pages.push(totalPages); } return pages; }; const startItem = (page - 1) * itemsPerPage + 1; const endItem = Math.min(page * itemsPerPage, totalItems); return ( Showing {startItem}-{endItem} of {totalItems} results setPage((p) => p - 1)}> Previous {getPageNumbers().map((p, i) => p === "ellipsis" ? ( ) : ( setPage(p)}> {p} ), )} setPage((p) => p + 1)}> Next ); } ``` ### Disabled ```tsx "use client"; import {Pagination} from "@heroui/react"; import {useState} from "react"; export function PaginationDisabled() { const [page, setPage] = useState(1); const totalPages = 3; return ( setPage((p) => p - 1)}> Previous {Array.from({length: totalPages}, (_, i) => i + 1).map((p) => ( setPage(p)}> {p} ))} setPage((p) => p + 1)}> Next ); } ``` ## Related Components - **Button**: Allows a user to perform an action - **Link**: Styled anchor links ## Styling ### Passing Tailwind CSS classes You can customize individual Pagination parts: ```tsx import { Pagination } from '@heroui/react'; function CustomPagination() { return ( 1 ); } ``` ### Customizing the component classes To customize the Pagination component classes, you can use the `@layer components` directive.
[Learn more](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes). ```css @layer components { .pagination { @apply gap-8; } .pagination__link { @apply rounded-md; } .pagination__summary { @apply text-xs font-semibold; } } ``` HeroUI follows the [BEM](https://getbem.com/) methodology to ensure component variants and states are reusable and easy to customize. ### CSS Classes The Pagination component uses these CSS classes ([View source styles](https://github.com/heroui-inc/heroui/blob/v3/packages/styles/components/pagination.css)): #### Base & Layout Classes - `.pagination` - Root navigation container with flex layout - `.pagination__summary` - Left-side info text container - `.pagination__content` - Container for pagination items - `.pagination__item` - Individual item wrapper - `.pagination__link` - Page number button (ghost button style) - `.pagination__link--nav` - Navigation button modifier (Previous/Next) - `.pagination__ellipsis` - Ellipsis indicator #### Size Classes - `.pagination--sm` - Small size variant - `.pagination--md` - Medium size variant (default) - `.pagination--lg` - Large size variant ### Interactive States The component supports both CSS pseudo-classes and data attributes for flexibility: - **Active page**: `[data-active="true"]` or `[aria-current="page"]` - **Hover**: `:hover` or `[data-hovered="true"]` - **Focus**: `:focus-visible` or `[data-focus-visible="true"]` - **Disabled**: `:disabled` or `[aria-disabled="true"]` - **Pressed**: `:active` or `[data-pressed="true"]` ## API Reference ### Pagination Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Size of the pagination items | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Pagination parts (Summary, Content) | ### Pagination.Summary Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Summary content (e.g., "Showing 1-10 of 120") | ### Pagination.Content Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Pagination items | ### Pagination.Item Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Item content (Link, Previous, Next, or Ellipsis) | ### Pagination.Link Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `isActive` | `boolean` | `false` | Whether this is the current page | | `isDisabled` | `boolean` | `false` | Whether the link is disabled | | `onPress` | `(e: PressEvent) => void` | - | Press handler (from React Aria) | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Page number content | ### Pagination.Previous / Pagination.Next Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `isDisabled` | `boolean` | `false` | Whether the button is disabled | | `onPress` | `(e: PressEvent) => void` | - | Press handler (from React Aria) | | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | - | Button content (compose with PreviousIcon/NextIcon) | ### Pagination.PreviousIcon / Pagination.NextIcon Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `className` | `string` | - | Additional CSS classes | | `children` | `ReactNode` | Default chevron SVG | Custom icon to replace the default chevron | ### Pagination.Ellipsis Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `className` | `string` | - | Additional CSS classes | ## Accessibility The Pagination component is built on [React Aria's Button](https://react-spectrum.adobe.com/react-aria/Button.html) primitive for all interactive elements, providing: - Semantic `