Skip to content
WANCRAFT

D.76Navigation & Menus

Fluid Pagination

Pagination with a sliding active indicator, smart ellipsis windowing and numbers that roll in the direction of travel.

NewReactMotionTailwindbasic

Overview

Fluid Pagination renders a nav landmark of page buttons whose active indicator slides between pages on a shared layout animation. Pages are windowed with ellipses around the current page using siblingCount and boundaryCount; the slot count stays constant, so as the window shifts the numbers roll up or down in place in the direction you are travelling. Previous and next buttons disable at the ends. A compact mode reads "Page 3 of 12" between two arrows for small screens, and the responsive variant switches between the two with a container query. The windowing logic is exported as the pure getPaginationRange helper.

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/fluid-pagination.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/fluid-pagination.json

Method 02 · Copy and paste

  1. 1. Install the dependencies below.
  2. 2. Copy the source from the Code tab into components/ui/fluid-pagination.tsx.
  3. 3. Import it and adjust props.
npm install motion
Dependencies
motion
Peer
react ≥ 18, tailwindcss ≥ 4
Added
13 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { FluidPagination } from "@/components/ui/fluid-pagination";
import { useState } from "react";

export function FluidPaginationExample() {
  const [page, setPage] = useState(1);

  return (
    <FluidPagination page={page} onPageChange={setPage} totalPages={20} />
  );
}

03Props

PropTypeDefaultDescription
totalPagesnumber—Number of pages (required).
pagenumber—Current page, 1-based (controlled).
defaultPagenumber1Initial page (uncontrolled).
onPageChange(page: number) => void—Called with the requested page.
siblingCountnumber1Pages shown on each side of the current page.
boundaryCountnumber1Pages always shown at the start and end.
variant"full" | "compact" | "responsive""full"Page list, Page n of N, or compact below a 28rem container width.
showPrevNextbooleantrueShow previous / next buttons in the full variant.
spring{ stiffness: number; damping: number; mass: number }{ stiffness: 420, damping: 34, mass: 0.8 }Spring for the sliding indicator.
accentstring"#FF7448"Active page and focus ring colour.
labelstring"Pagination"Accessible name of the nav landmark.
previousLabelstring"Previous page"Accessible name of the previous button.
nextLabelstring"Next page"Accessible name of the next button.
...propsHTMLAttributes<HTMLElement>—Native attributes are forwarded to the <nav>.

04Features

  • 01Shared-layout active indicator that slides between pages on a spring
  • 02Ellipsis windowing with siblingCount and boundaryCount; a lone hidden page is shown instead of an ellipsis
  • 03Constant slot count, so numbers roll up or down in place as the window shifts
  • 04Previous / next buttons that disable at the ends
  • 05Compact "Page 3 of 12" mode and a container-query responsive variant
  • 06Exports the pure getPaginationRange helper for custom renderers and tests
motion · layoutmotion · springmotion · tweeninput · clickinput · keyboard

05Accessibility

  • Rendered as a <nav> landmark with an accessible name around a real list of buttons.
  • The current page carries aria-current="page"; every page button is named "Page n".
  • Previous / next are labelled buttons that use the disabled attribute at the ends.
  • Ellipses are aria-hidden; the compact mode announces "Page n of N" through a polite live region.
  • With prefers-reduced-motion the indicator jumps and numbers change without rolling.