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
Installation
npx @gentleduck/cli add pagination
npx @gentleduck/cli add pagination
Usage
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>
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>
)
Component Composition
RTL Support
Set the direction once with DirectionProvider (or <html dir="rtl">) and the pagination mirrors itself: keep markup in logical order (Previous, pages, Next) and the chevrons flip automatically. Use the text and aria-label props on PaginationPrevious, PaginationNext, and PaginationEllipsis to translate the labels.
Motion
Use MotionPagination with MotionPaginationLink, MotionPaginationPrevious, and MotionPaginationNext for staggered entrance animations and tap feedback powered by motion. Each link uses a scaleIn entrance (fade, scale, and blur) with a bouncy spring transition, staggered by 50ms via the index prop.
motion package. Use the Motion* variants instead of the base components. Same props plus index for stagger delay. The regular components are perfectly fine - this is an optional enhancement.API Reference
Pagination
| Prop | Type | Default | Description |
|---|---|---|---|
dir | 'ltr' | 'rtl' | - | Text direction override. Resolved via useDirection (dir prop -> DirectionProvider -> <html dir>). |
className | string | -- | Additional CSS classes for the nav element |
...props | React.ComponentPropsWithoutRef<'nav'> | - | Additional props to spread to the nav element |
PaginationContent
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes for the ul element |
...props | React.ComponentPropsWithoutRef<'ul'> | - | Additional props to spread to the ul element |
PaginationItem
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | -- | Additional CSS classes for the li element |
...props | React.ComponentPropsWithoutRef<'li'> | - | Additional props to spread to the li element |
PaginationLink
| Prop | Type | Default | Description |
|---|---|---|---|
isActive | boolean | - | Marks the link as active/current page (adds aria-current="page" and styles) |
size | 'icon' | 'default' | 'sm' | 'icon' | Size variant for the button style |
...props | React.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.
| Prop | Type | Default | Description |
|---|---|---|---|
text | string | 'Previous' | Visible label text. Override for i18n / RTL support. |
className | string | -- | Additional CSS classes for the previous link |
...props | React.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.
| Prop | Type | Default | Description |
|---|---|---|---|
text | string | 'Next' | Visible label text. Override for i18n / RTL support. |
className | string | -- | Additional CSS classes for the next link |
...props | React.ComponentPropsWithoutRef<typeof PaginationLink> | - | Additional props inherited from PaginationLink. |
PaginationEllipsis
| Prop | Type | Default | Description |
|---|---|---|---|
text | string | 'More pages' | Screen-reader label text. Override for i18n / RTL support. |
className | string | -- | Additional CSS classes for the ellipsis element |
...props | React.ComponentPropsWithoutRef<'span'> | - | Additional props to spread to the span element |
PaginationWrapper
| Prop | Type | Default | Description |
|---|---|---|---|
wrapper | React.ComponentPropsWithoutRef<typeof Pagination> | - | Props for the pagination container |
content | React.ComponentPropsWithoutRef<typeof PaginationContent> | - | Props for the content list |
item | React.ComponentPropsWithoutRef<typeof PaginationItem> | - | Props for each pagination item |
right | React.ComponentPropsWithoutRef<typeof Button> | - | Props for the "Next" button |
maxRight | React.ComponentPropsWithoutRef<typeof Button> | - | Props for the "Last" button |
left | React.ComponentPropsWithoutRef<typeof Button> | - | Props for the "Previous" button |
maxLeft | React.ComponentPropsWithoutRef<typeof Button> | - | Props for the "First" button |
The wrapper follows DirectionProvider (or <html dir>) like the other parts. Pass dir through wrapper only to override it locally:
<PaginationWrapper wrapper={{ dir: 'rtl' }} />
MotionPagination
scaleIn entrance (fade, scale, and blur) with springBouncy transition on mount. Requires the motion package.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | PaginationProps | - | All props from Pagination are supported |
MotionPaginationLink
Staggered scaleIn entrance (fade, scale, and blur) + whileTap press feedback (scale 0.97). Requires the motion package.
| Prop | Type | Default | Description |
|---|---|---|---|
index | number | 0 | Stagger delay index (50ms per index) for entrance animation |
...props | PaginationLinkProps | - | All props from PaginationLink are supported |
MotionPaginationPrevious
Uses MotionPaginationLink internally with preset icon and label. Requires the motion package.
| Prop | Type | Default | Description |
|---|---|---|---|
index | number | 0 | Stagger delay index (50ms per index) for entrance animation |
text | string | 'Previous' | Label text shown alongside the chevron |
...props | PaginationLinkProps | - | All other props from PaginationLink are supported |
MotionPaginationNext
Uses MotionPaginationLink internally with preset icon and label. Requires the motion package.
| Prop | Type | Default | Description |
|---|---|---|---|
index | number | 0 | Stagger delay index (50ms per index) for entrance animation |
text | string | 'Next' | Label text shown alongside the chevron |
...props | PaginationLinkProps | - | All other props from PaginationLink are supported |