Navigation

Pagination

A structured navigation system that divides content into multiple pages, improving load performance and user experience.

Basic

Pagination is a navigation component that allows users to move through multiple pages. It’s composed of several elements working together to provide a smooth user experience.

Loading...

Installation

npx shadcn@latest add @intentui/pagination

Composed components

When you install this component via the CLI, it automatically loads all composed components, so you don’t need to add them individually.

This component comes packed with several components to enhance functionality and provide a seamless experience.

Manual installation

npm i react-aria-components @intentui/icons

Anatomy

import {
  Pagination,
  PaginationItem,
  PaginationList,
  PaginationSection,
} from "@/components/ui/pagination"
<Pagination>
  <PaginationList>
    <PaginationItem segment="first" href="#" />
    <PaginationItem segment="previous" href="#" />
    <PaginationSection
      aria-label="Pagination Segment"
      className="rounded-lg border lg:hidden"
    >
      <PaginationItem segment="label">1</PaginationItem>
      <PaginationItem segment="separator" />
      <PaginationItem className="text-muted-fg" segment="label">
        10
      </PaginationItem>
    </PaginationSection>
    <PaginationSection
      aria-label="Pagination Segment"
      className="hidden lg:flex"
    >
      <PaginationItem href="#">1</PaginationItem>
    </PaginationSection>
    <PaginationItem segment="next" href="#" />
    <PaginationItem segment="last" href="#" />
  </PaginationList>
</Pagination>

Simple

The simple pagination setup doesn’t display page numbers, using only basic arrow navigation.

Loading...

Using collections

Since the pagination list is part of the GridList primitive, handling collections is easy. Just pass the collections into the PaginationList using the items prop.

Loading...

Preserving scroll

Sometimes, you need to prevent the page from scrolling to the top when users interact with pagination. You can do this by passing scroll-related props from your routerOptions into the PaginationLink component.

Inertia.js

When using Inertia.js, you can use the preserveScroll prop to keep the page from scrolling to the top during pagination interactions.

<PaginationList aria-label="Pagination Segment" items={pages}>
  {(item) => (
    <PaginationItem
      routerOptions={{ preserveScroll: true }}
      id={item.label.toString()}
      isCurrent={item.isCurrent}
      href={item.url ?? ''}
    >

Next.js

When using Next.js, apply the scroll prop to stop the page from scrolling to the top when users navigate through pagination.

<PaginationList aria-label="Pagination Segment" items={pages}>
  {(item) => (
    <PaginationItem
      routerOptions={{ scroll: false }}
      id={item.label.toString()}
      isCurrent={item.isCurrent}
      href={item.url ?? ''}
    >

Remix

When using Remix, you can add the preventScrollReset prop to prevent the page from scrolling to the top when users interact with pagination.

<PaginationList aria-label="Pagination Segment" items={pages}>
  {(item) => (
    <PaginationItem
      routerOptions={{ preventScrollReset: true }}
      id={item.label.toString()}
      isCurrent={item.isCurrent}
      href={item.url ?? ''}
    >

React router

If you're using React Router, check out this tutorial for guidance. After that, give it a go on your own. Apologies, I'm not fully up to speed with the latest updates in React Router.

Considering

You might be thinking, "Why not just bake this functionality directly into the Pagination component, right?" But it's not that simple. I tried integrating it into the Pagination setup, but when you start mixing in other functionalities, like those Inertia.js router options, things can get messy. So, I kept it straightforward to avoid any conflicts.

const renderListItem = (
  props: ListBoxItemProps & {
    textValue?: string
    ariaCurrent?: string | undefined
    isDisabled?: boolean
    className?: string
  },
  children: React.ReactNode
) => (
  <ListBoxItem routerOptions={{ preserveScroll: true, ...props.routerOptions }} {...props}>
    {children}
  </ListBoxItem>
)

So here's how I roll with it:

 <PaginationList aria-label="Pagination Segment" items={paginate.pages}>
  {(item) => (
    <PaginationItem
      routerOptions={{ only: ['series'] }}
      id={item.label.toString()}
      isCurrent={item.isCurrent}
      href={item.url ?? ''}
    >
      {item.label}
    </PaginationItem>
  )}
</PaginationList>

I figured it'd be chill, but nah, it ain't cuttin' it. That’s why I’m throwin' this idea your way: toss that option in when you're rockin' the pagination component. Ain’t sayin' it's top shelf, but it’s one way to roll.

Client side routing

Make sure you have read Client Side Routing before using this component.

Unlock the full power of
Design Intent UI
Build modern web apps faster with 350+ blocks and polished templates crafted for professionals.
Explore