Skip to main content

Overview

The Pagination component provides a flexible way to navigate through pages of content, with support for sibling page display, edge buttons, and different sizes.

Import

import { Pagination } from '@kivora/react';

Basic Usage

const [page, setPage] = useState(1);

<Pagination 
  total={10} 
  value={page} 
  onChange={setPage} 
/>

Uncontrolled

<Pagination 
  total={10} 
  defaultValue={1}
  onChange={(page) => console.log('Page:', page)}
/>

With Edge Buttons

<Pagination 
  total={20} 
  value={page} 
  onChange={setPage}
  withEdges
/>

Sibling Pages

Control how many page numbers appear on each side of the current page:
<Pagination 
  total={50} 
  value={page} 
  onChange={setPage}
  siblings={2}
/>

Sizes

{/* Small */}
<Pagination total={10} size="sm" />

{/* Medium (default) */}
<Pagination total={10} size="md" />

{/* Large */}
<Pagination total={10} size="lg" />

Disabled State

<Pagination 
  total={10} 
  value={5}
  disabled
/>

Complete Example

import { useState } from 'react';
import { Pagination } from '@kivora/react';

function DataTable() {
  const [currentPage, setCurrentPage] = useState(1);
  const totalPages = 25;
  const itemsPerPage = 10;

  const startIndex = (currentPage - 1) * itemsPerPage;
  const endIndex = startIndex + itemsPerPage;
  const currentData = data.slice(startIndex, endIndex);

  return (
    <div>
      <div className="space-y-2">
        {currentData.map(item => (
          <div key={item.id}>{item.name}</div>
        ))}
      </div>
      
      <Pagination
        total={totalPages}
        value={currentPage}
        onChange={setCurrentPage}
        siblings={1}
        withEdges
        className="mt-6"
      />
    </div>
  );
}

Props

PaginationProps

PropTypeDefaultDescription
totalnumberrequiredTotal number of pages
valuenumberundefinedCurrent page (1-based, controlled)
defaultValuenumber1Default page for uncontrolled mode
onChange(page: number) => voidundefinedCalled when page changes
siblingsnumber1Number of sibling pages visible on each side
withEdgesbooleanfalseWhether to show first/last page buttons
disabledbooleanfalseDisable all interactions
size'sm' | 'md' | 'lg''md'Button size variant
classNamestring''Additional CSS classes

Size Dimensions

SizeButton SizeFont Size
sm28px × 28px12px
md32px × 32px14px
lg40px × 40px16px

Page Range Algorithm

The component intelligently shows page numbers based on the current page:
  • Always shows first and last page
  • Shows siblings number of pages on each side of current page
  • Inserts ellipsis () when there’s a gap
  • Condenses to direct page numbers when total pages is small

Example with siblings=:

  • Page 1 of 10: [1] 2 … 10
  • Page 5 of 10: 1 … 4 [5] 6 … 10
  • Page 10 of 10: 1 … 9 [10]
  • Previous page
  • Next page
  • « First page (when withEdges={true})
  • » Last page (when withEdges={true})

Accessibility

  • Wrapped in semantic <nav> with aria-label="Pagination"
  • Current page button has aria-current="page"
  • Previous/Next buttons have descriptive aria-label attributes
  • Edge buttons have “First page” and “Last page” labels
  • Disabled states prevent interaction
  • Focus visible ring for keyboard navigation
  • All buttons are properly labeled for screen readers

Controlled vs Uncontrolled

Controlled: Use value and onChange props when you need to manage page state externally.
const [page, setPage] = useState(1);
<Pagination total={10} value={page} onChange={setPage} />
Uncontrolled: Use defaultValue when the component manages its own state.
<Pagination total={10} defaultValue={1} onChange={(p) => console.log(p)} />

Build docs developers (and LLMs) love