Skip to main content

pagination

Pagination with page navigation, next and previous links.

Philosophy

Pagination is a navigation pattern, not a data-fetching pattern. We provide the visual components (page buttons, next/previous, ellipsis) and let you wire them to your data layer. This separation means the same pagination UI works whether you're paginating a client-side array, an API, or a database cursor. Under the hood, this component composes @gentleduck/primitives/pagination for semantic structure and direction-aware behavior.

Installation


npx @gentleduck/cli add pagination

npx @gentleduck/cli add pagination

Usage

import {
  Pagination,
  PaginationContent,
  PaginationEllipsis,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination"
import {
  Pagination,
  PaginationContent,
  PaginationEllipsis,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination"
<Pagination>
  <PaginationContent>
    <PaginationItem>
      <PaginationPrevious href="#" />
    </PaginationItem>
    <PaginationItem>
      <PaginationLink href="#">1</PaginationLink>
    </PaginationItem>
    <PaginationItem>
      <PaginationEllipsis />
    </PaginationItem>
    <PaginationItem>
      <PaginationNext href="#" />
    </PaginationItem>
  </PaginationContent>
</Pagination>
<Pagination>
  <PaginationContent>
    <PaginationItem>
      <PaginationPrevious href="#" />
    </PaginationItem>
    <PaginationItem>
      <PaginationLink href="#">1</PaginationLink>
    </PaginationItem>
    <PaginationItem>
      <PaginationEllipsis />
    </PaginationItem>
    <PaginationItem>
      <PaginationNext href="#" />
    </PaginationItem>
  </PaginationContent>
</Pagination>

Next.js

By default the <PaginationLink /> component will render an <a /> tag.

To use the Next.js <Link /> component, make the following updates to pagination.tsx.

+ import Link from "next/link"
 
- type PaginationLinkProps = ... & React.ComponentPropsWithoutRef<"a">
+ type PaginationLinkProps = ... & React.ComponentProps<typeof Link>
 
const PaginationLink = ({...props }: ) => (
  <PaginationItem>
-   <a>
+   <Link>
      // ...
-   </a>
+   </Link>
  </PaginationItem>
)
 
+ import Link from "next/link"
 
- type PaginationLinkProps = ... & React.ComponentPropsWithoutRef<"a">
+ type PaginationLinkProps = ... & React.ComponentProps<typeof Link>
 
const PaginationLink = ({...props }: ) => (
  <PaginationItem>
-   <a>
+   <Link>
      // ...
-   </a>
+   </Link>
  </PaginationItem>
)
 

Component Composition

Loading diagram...

API Reference

Pagination

PropTypeDefaultDescription
dir'ltr' | 'rtl'--Text direction override. Resolved via useDirection (dir prop -> DirectionProvider -> 'ltr').
classNamestring--Additional CSS classes for the nav element
...propsReact.ComponentPropsWithoutRef<'nav'>--Additional props to spread to the nav element

PaginationContent

PropTypeDefaultDescription
classNamestring--Additional CSS classes for the ul element
...propsReact.ComponentPropsWithoutRef<'ul'>--Additional props to spread to the ul element

PaginationItem

PropTypeDefaultDescription
classNamestring--Additional CSS classes for the li element
...propsReact.ComponentPropsWithoutRef<'li'>--Additional props to spread to the li element
PropTypeDefaultDescription
isActiveboolean--Marks the link as active/current page (adds aria-current="page" and styles)
size'icon' | 'default' | 'sm''icon'Size variant for the button style
...propsReact.ComponentPropsWithoutRef<'a'>--Additional props to spread to the a element

PaginationPrevious

Extends PaginationLink with aria-label="Go to previous page", left arrow icon, and text "Previous". Uses 'default' size.

PropTypeDefaultDescription
textstring'Previous'Visible label text. Override for i18n / RTL support.
classNamestring--Additional CSS classes for the previous link
...propsReact.ComponentPropsWithoutRef<typeof PaginationLink>--Additional props inherited from PaginationLink.

PaginationNext

Extends PaginationLink with aria-label="Go to next page", text "Next", and right arrow icon. Uses 'default' size.

PropTypeDefaultDescription
textstring'Next'Visible label text. Override for i18n / RTL support.
classNamestring--Additional CSS classes for the next link
...propsReact.ComponentPropsWithoutRef<typeof PaginationLink>--Additional props inherited from PaginationLink.

PaginationEllipsis

PropTypeDefaultDescription
textstring'More pages'Screen-reader label text. Override for i18n / RTL support.
classNamestring--Additional CSS classes for the ellipsis element
...propsReact.ComponentPropsWithoutRef<'span'>--Additional props to spread to the span element

PaginationWrapper

PropTypeDefaultDescription
wrapperReact.ComponentPropsWithoutRef<typeof Pagination>--Props for the pagination container
contentReact.ComponentPropsWithoutRef<typeof PaginationContent>--Props for the content list
itemReact.ComponentPropsWithoutRef<typeof PaginationItem>--Props for each pagination item
rightReact.ComponentPropsWithoutRef<typeof Button>--Props for the "Next" button
maxRightReact.ComponentPropsWithoutRef<typeof Button>--Props for the "Last" button
leftReact.ComponentPropsWithoutRef<typeof Button>--Props for the "Previous" button
maxLeftReact.ComponentPropsWithoutRef<typeof Button>--Props for the "First" button

You can pass dir: 'rtl' through wrapper to make wrapper controls direction-aware:

<PaginationWrapper wrapper={{ dir: 'rtl' }} />
<PaginationWrapper wrapper={{ dir: 'rtl' }} />

RTL Support

Use the text prop on PaginationPrevious, PaginationNext, and PaginationEllipsis to provide translated labels. Set dir="rtl" on Pagination for a local override, or set DirectionProvider once at app/root level for global direction. Keep markup in logical order (Previous, pages, Next): visual mirroring is handled automatically.