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.

How It's Built

Loading diagram...

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>

Examples

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...

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.

Motion

Use MotionPagination with MotionPaginationLink, MotionPaginationPrevious, and MotionPaginationNext for staggered entrance animations and tap feedback powered by motion. Each link fades in with scale and blur, staggered by 50ms via the index prop.

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' }} />

MotionPagination

scaleIn entrance with springBouncy transition on mount. Requires the motion package.

PropTypeDefaultDescription
...propsPaginationProps-All props from Pagination are supported

Staggered scaleIn entrance + whileTap press feedback (scale 0.97). Requires the motion package.

PropTypeDefaultDescription
indexnumber0Stagger delay index (50ms per index) for entrance animation
...propsPaginationLinkProps-All props from PaginationLink are supported

MotionPaginationPrevious

Uses MotionPaginationLink internally with preset icon and label. Requires the motion package.

PropTypeDefaultDescription
indexnumber0Stagger delay index (50ms per index) for entrance animation
textstring'Previous'Label text shown alongside the chevron
...propsPaginationLinkProps-All other props from PaginationLink are supported

MotionPaginationNext

Uses MotionPaginationLink internally with preset icon and label. Requires the motion package.

PropTypeDefaultDescription
indexnumber0Stagger delay index (50ms per index) for entrance animation
textstring'Next'Label text shown alongside the chevron
...propsPaginationLinkProps-All other props from PaginationLink are supported