> ## Documentation Index
> Fetch the complete documentation index at: https://araf.badr.co.id/llms.txt
> Use this file to discover all available pages before exploring further.

# Pagination

> A navigation control for moving between pages of a paginated dataset — supports ellipsis for large page counts and 3 sizes.

## Overview

<div style={{padding:"28px 24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb"}}>
  <div style={{display:"flex",alignItems:"center",gap:"4px",justifyContent:"center",flexWrap:"wrap"}}>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#71717A",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px"}}>‹</button>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#344054",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px",fontFamily:"Inter,sans-serif",fontWeight:500}}>1</button>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #0479CE",background:"#0479CE",color:"#fff",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px",fontFamily:"Inter,sans-serif",fontWeight:500}}>2</button>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#344054",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px",fontFamily:"Inter,sans-serif",fontWeight:500}}>3</button>
    <span style={{width:"36px",height:"36px",display:"flex",alignItems:"center",justifyContent:"center",color:"#71717A",fontSize:"14px"}}>...</span>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#344054",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px",fontFamily:"Inter,sans-serif",fontWeight:500}}>10</button>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#71717A",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px"}}>›</button>
  </div>
</div>

**Pagination** renders page number buttons, previous/next arrows, and an ellipsis for large page counts. It can be controlled or uncontrolled and pairs naturally with the Table component.

***

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install @araf-ds/core
  ```

  ```bash yarn theme={null}
  yarn add @araf-ds/core
  ```

  ```bash pnpm theme={null}
  pnpm add @araf-ds/core
  ```
</CodeGroup>

***

## Usage

```tsx theme={null}
import { Pagination } from "@araf-ds/core"

export default function Example() {
  const [page, setPage] = useState(1)
  return (
    <Pagination
      page={page}
      totalPages={10}
      onPageChange={setPage}
    />
  )
}
```

***

## Variants

### Basic

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb"}}>
  <div style={{display:"flex",alignItems:"center",gap:"4px",justifyContent:"center"}}>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#71717A",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px"}}>‹</button>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #0479CE",background:"#0479CE",color:"#fff",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px",fontFamily:"Inter,sans-serif",fontWeight:500}}>1</button>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#344054",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px",fontFamily:"Inter,sans-serif",fontWeight:500}}>2</button>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#344054",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px",fontFamily:"Inter,sans-serif",fontWeight:500}}>3</button>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#344054",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px",fontFamily:"Inter,sans-serif",fontWeight:500}}>4</button>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#344054",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px",fontFamily:"Inter,sans-serif",fontWeight:500}}>5</button>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#71717A",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px"}}>›</button>
  </div>
</div>

```tsx theme={null}
<Pagination totalPages={5} defaultPage={1} onPageChange={(p) => console.log(p)} />
```

### With Ellipsis (Many Pages)

<div style={{padding:"24px",background:"#f9fafb",borderRadius:"12px",border:"1px solid #e5e7eb"}}>
  <div style={{display:"flex",alignItems:"center",gap:"4px",justifyContent:"center"}}>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#71717A",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px"}}>«</button>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#344054",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px",fontFamily:"Inter,sans-serif",fontWeight:500}}>1</button>
    <span style={{width:"36px",height:"36px",display:"flex",alignItems:"center",justifyContent:"center",color:"#71717A",fontSize:"14px"}}>...</span>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#344054",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px",fontFamily:"Inter,sans-serif",fontWeight:500}}>6</button>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #0479CE",background:"#0479CE",color:"#fff",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px",fontFamily:"Inter,sans-serif",fontWeight:500}}>7</button>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#344054",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px",fontFamily:"Inter,sans-serif",fontWeight:500}}>8</button>
    <span style={{width:"36px",height:"36px",display:"flex",alignItems:"center",justifyContent:"center",color:"#71717A",fontSize:"14px"}}>...</span>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#344054",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px",fontFamily:"Inter,sans-serif",fontWeight:500}}>50</button>
    <button style={{width:"36px",height:"36px",borderRadius:"8px",border:"1px solid #E5E7EB",background:"#fff",color:"#71717A",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",fontSize:"14px"}}>»</button>
  </div>
</div>

```tsx theme={null}
<Pagination
  page={7}
  totalPages={50}
  siblingCount={1}
  onPageChange={setPage}
/>
{/* renders: « 1 ... 6 [7] 8 ... 50 » */}
```

### Usage with Data Table

```tsx theme={null}
function UsersTable({ users }: { users: User[] }) {
  const [page, setPage] = useState(1);
  const pageSize = 10;
  const totalPages = Math.ceil(users.length / pageSize);
  const visibleUsers = users.slice((page - 1) * pageSize, page * pageSize);

  return (
    <div>
      <Table>
        {/* rows from visibleUsers */}
      </Table>
      <div className="flex justify-end mt-4">
        <Pagination
          page={page}
          totalPages={totalPages}
          onPageChange={setPage}
        />
      </div>
    </div>
  );
}
```

***

## API Reference

<ParamField path="page" type="number">
  Controlled current page (1-indexed).
</ParamField>

<ParamField path="onPageChange" type="(page: number) => void">
  Callback fired when the user navigates to a different page.
</ParamField>

<ParamField path="defaultPage" type="number" default="1">
  Uncontrolled default page.
</ParamField>

<ParamField path="totalPages" type="number">
  Total number of pages (required).
</ParamField>

<ParamField path="siblingCount" type="number" default="1">
  Number of page buttons shown on each side of the current page.
</ParamField>

<ParamField path="showFirstLast" type="boolean" default="true">
  Shows first («) and last (») page jump buttons.
</ParamField>

<ParamField path="size" type="string" default="md">
  Button size. Values: `sm` · `md` · `lg`
</ParamField>

<ParamField path="className" type="string">
  Additional Tailwind classes for custom overrides.
</ParamField>

***

## Accessibility

* Pagination uses a `<nav>` element with `aria-label="Pagination"`
* Active page button has `aria-current="page"`
* Disabled previous/next buttons have `aria-disabled="true"`
* Ellipsis elements use `aria-hidden="true"` as they are decorative
* Previous/Next buttons have descriptive `aria-label` attributes

***

## Do's & Don'ts

<CardGroup cols={2}>
  <Card title="Do" icon="check" iconType="solid" color="#16A34A">
    * Always pair Pagination with a data table or list
    * Show the total count of items alongside the pagination control
    * Use `siblingCount={2}` for very large datasets (100+ pages)
    * Keep the Pagination at the bottom of the data, aligned to the right
  </Card>

  <Card title="Don't" icon="xmark" iconType="solid" color="#DC2626">
    * Don't use Pagination for fewer than 2 pages — hide it entirely
    * Don't change `totalPages` during interaction unless data has changed
    * Don't place Pagination above the data — users expect it at the bottom
    * Don't use Pagination when infinite scroll is more appropriate for the UX
  </Card>
</CardGroup>
