Fragiola UI
Navigation

Pagination

A strip of links where one is the current page. Every clickable part is `Clickable` — there is no button style in this file. The current page carries `aria-current="page"` and is distinguished by a fill strategy, never by a colour.

npx shadcn@latest add @fragiola/pagination
with ellipsis
previous disabled
Show code
"use client";

import type { ReactNode } from "react";
import { Pagination } from "#/ui/pagination";

// The floor is palette-surface. The pagination links and the active state
// read roles from the floor — the active link uses contrast, the rest use
// accent. Shows: basic, with ellipsis, and previous disabled at the start.
export default function PaginationDemo() {
    return (
        <div className="palette-surface flex flex-col gap-6 rounded-lg border border-palette-line bg-palette-base p-6">
            <Row label="basic">
                <Pagination.Root>
                    <Pagination.Content>
                        <Pagination.Item>
                            <Pagination.Previous href="?page=1" />
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Link href="?page=1">1</Pagination.Link>
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Link href="?page=2" active>
                                2
                            </Pagination.Link>
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Link href="?page=3">3</Pagination.Link>
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Link href="?page=4">4</Pagination.Link>
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Link href="?page=5">5</Pagination.Link>
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Next href="?page=3" />
                        </Pagination.Item>
                    </Pagination.Content>
                </Pagination.Root>
            </Row>

            <Row label="with ellipsis">
                <Pagination.Root>
                    <Pagination.Content>
                        <Pagination.Item>
                            <Pagination.Previous href="?page=1" />
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Link href="?page=1">1</Pagination.Link>
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Ellipsis />
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Link href="?page=8">8</Pagination.Link>
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Link href="?page=9" active>
                                9
                            </Pagination.Link>
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Link href="?page=10">
                                10
                            </Pagination.Link>
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Ellipsis />
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Link href="?page=20">
                                20
                            </Pagination.Link>
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Next href="?page=10" />
                        </Pagination.Item>
                    </Pagination.Content>
                </Pagination.Root>
            </Row>

            <Row label="previous disabled">
                <Pagination.Root>
                    <Pagination.Content>
                        <Pagination.Item>
                            <Pagination.Previous href="?page=1" disabled />
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Link href="?page=1" active>
                                1
                            </Pagination.Link>
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Link href="?page=2">2</Pagination.Link>
                        </Pagination.Item>
                        <Pagination.Item>
                            <Pagination.Next href="?page=2" />
                        </Pagination.Item>
                    </Pagination.Content>
                </Pagination.Root>
            </Row>
        </div>
    );
}

function Row({ label, children }: { label: string; children: ReactNode }) {
    return (
        <div className="flex flex-col gap-2">
            <span className="text-xs font-mono text-palette-accent/85">
                {label}
            </span>
            {children}
        </div>
    );
}

All Clickable, no button style

Link is Clickable.Link, Previous and Next are Clickable.Link with an icon. The current page uses variant="outline" (a fill strategy), not a colour. The previous/next chevrons invert under RTL via rtl:rotate-180 — there is no logical utility for icon direction.

Parts

PartSource
Root<nav aria-label>
LinkClickable.Link
Previous / NextClickable.Link + icon
Ellipsisdecorative <span> + sr-only

On this page