Skip to main content
The Pagination component provides navigation controls for moving between pages of content. It automatically handles the display of page numbers with ellipsis for large page counts.

Basic Usage

import { Pagination } from 'reshaped';

function App() {
  return (
    <Pagination
      total={10}
      defaultPage={1}
      previousAriaLabel="Previous page"
      nextAriaLabel="Next page"
    />
  );
}

Controlled Mode

Control the current page externally:
import { Pagination } from 'reshaped';
import { useState } from 'react';

function App() {
  const [currentPage, setCurrentPage] = useState(1);
  
  return (
    <Pagination
      total={20}
      page={currentPage}
      onChange={({ page }) => setCurrentPage(page)}
      previousAriaLabel="Previous page"
      nextAriaLabel="Next page"
    />
  );
}

With Page Labels

Provide custom aria labels for each page:
<Pagination
  total={10}
  defaultPage={1}
  pageAriaLabel={({ page }) => `Go to page ${page}`}
  previousAriaLabel="Go to previous page"
  nextAriaLabel="Go to next page"
/>

Basic Pagination

function DataTable() {
  const [page, setPage] = useState(1);
  const itemsPerPage = 10;
  const totalItems = 250;
  const totalPages = Math.ceil(totalItems / itemsPerPage);
  
  const startIndex = (page - 1) * itemsPerPage;
  const endIndex = startIndex + itemsPerPage;
  const currentItems = items.slice(startIndex, endIndex);
  
  return (
    <>
      <Table data={currentItems} />
      <Pagination
        total={totalPages}
        page={page}
        onChange={({ page }) => setPage(page)}
        previousAriaLabel="Previous page"
        nextAriaLabel="Next page"
      />
    </>
  );
}

With URL Synchronization

import { useSearchParams } from 'react-router-dom';

function SearchResults() {
  const [searchParams, setSearchParams] = useSearchParams();
  const currentPage = parseInt(searchParams.get('page') || '1');
  
  const handlePageChange = ({ page }) => {
    setSearchParams({ page: page.toString() });
  };
  
  return (
    <>
      <Results page={currentPage} />
      <Pagination
        total={50}
        page={currentPage}
        onChange={handlePageChange}
        previousAriaLabel="Previous page"
        nextAriaLabel="Next page"
      />
    </>
  );
}

Infinite Scroll Alternative

function PaginatedContent() {
  const [page, setPage] = useState(1);
  
  return (
    <View gap={4}>
      <Content page={page} />
      
      <View align="center">
        <Pagination
          total={100}
          page={page}
          onChange={({ page }) => {
            setPage(page);
            window.scrollTo({ top: 0, behavior: 'smooth' });
          }}
          previousAriaLabel="Previous page"
          nextAriaLabel="Next page"
        />
      </View>
    </View>
  );
}

Page Display Logic

The Pagination component automatically handles the display of page numbers:
  • Shows ellipsis (…) when there are many pages
  • Always shows the first and last pages
  • Shows pages around the current selection
  • Adapts the display based on the total number of pages
{/* Few pages: 1 2 3 4 5 */}
<Pagination total={5} page={3} />

{/* Many pages: 1 ... 5 6 7 ... 20 */}
<Pagination total={20} page={6} />

{/* Near start: 1 2 3 4 ... 20 */}
<Pagination total={20} page={2} />

{/* Near end: 1 ... 17 18 19 20 */}
<Pagination total={20} page={19} />

Props

Pagination

total
number
required
Total number of pages available
page
number
Currently selected page number, starts with 1 (controlled mode)
defaultPage
number
Default selected page number, starts with 1 (uncontrolled mode)
onChange
(args: { page: number }) => void
Callback when the current page changes
pageAriaLabel
(args: { page: number }) => string
Function to dynamically get an aria-label for each page button
previousAriaLabel
string
required
aria-label attribute for the previous page button
nextAriaLabel
string
required
aria-label attribute for the next page button
className
string
Additional CSS class name
attributes
object
Additional HTML attributes

Build docs developers (and LLMs) love