FluxUI Pro is live - modern UI, powerful animations, zero hassle.
Components
Advanced Pagination

Advanced Pagination

Sophisticated page navigation with animated transitions, page size controls, and accessibility features.

5
of 20 pages
Showing 41-50 of 200 items
Jump to:

Installation

1

Install the packages

npm i motion clsx tailwind-merge react-icons
2

Add util file

lib/util.ts
import { ClassValue, clsx } from "clsx"; import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); }
3

Copy and paste the following code into your project

advanced-pagination.tsx
"use client"; import { motion } from "motion/react"; import { useState } from "react"; import { cn } from "@/lib/utils"; import { FiChevronLeft, FiChevronRight, FiMoreHorizontal } from "react-icons/fi"; type AdvancedPaginationProps = { currentPage?: number; totalPages?: number; onPageChange?: (page: number) => void; showPageSize?: boolean; }; const AdvancedPagination = ({ currentPage: initialPage = 1, totalPages = 10, onPageChange = () => {}, showPageSize = true, }: AdvancedPaginationProps) => { const [currentPage, setCurrentPage] = useState(initialPage); const [pageSize, setPageSize] = useState(10); const handlePageChange = (page: number) => { if (page >= 1 && page <= totalPages) { setCurrentPage(page); onPageChange(page); } }; const getVisiblePages = () => { const delta = 2; const range = []; const rangeWithDots = []; for (let i = Math.max(2, currentPage - delta); i <= Math.min(totalPages - 1, currentPage + delta); i++) { range.push(i); } if (currentPage - delta > 2) { rangeWithDots.push(1, '...'); } else { rangeWithDots.push(1); } rangeWithDots.push(...range); if (currentPage + delta < totalPages - 1) { rangeWithDots.push('...', totalPages); } else if (totalPages > 1) { rangeWithDots.push(totalPages); } return rangeWithDots; }; const visiblePages = getVisiblePages(); return ( <div className="w-full max-w-2xl mx-auto"> <div className="flex flex-col sm:flex-row items-center justify-between gap-4"> {/* Page size selector */} {showPageSize && ( <div className="flex items-center gap-2"> <span className="text-sm text-neutral-600 dark:text-neutral-400">Show:</span> <select value={pageSize} onChange={(e) => setPageSize(Number(e.target.value))} className="px-3 py-1 text-sm border border-neutral-300 dark:border-neutral-600 rounded bg-white dark:bg-neutral-800 text-neutral-900 dark:text-white" > <option value={5}>5</option> <option value={10}>10</option> <option value={25}>25</option> <option value={50}>50</option> </select> <span className="text-sm text-neutral-600 dark:text-neutral-400">per page</span> </div> )} {/* Pagination controls */} <div className="flex items-center gap-1"> {/* Previous button */} <motion.button className={cn( "p-2 rounded-md border transition-all duration-200", currentPage === 1 ? "border-neutral-200 dark:border-neutral-700 text-neutral-400 cursor-not-allowed" : "border-neutral-300 dark:border-neutral-600 text-neutral-700 dark:text-neutral-300 hover:bg-neutral-50 dark:hover:bg-neutral-800" )} onClick={() => handlePageChange(currentPage - 1)} disabled={currentPage === 1} whileTap={{ scale: 0.95 }} > <FiChevronLeft className="w-4 h-4" /> </motion.button> {/* Page numbers */} {visiblePages.map((page, index) => ( <motion.button key={index} className={cn( "px-3 py-2 mx-0.5 rounded-md border transition-all duration-200 text-sm font-medium", page === currentPage ? "bg-blue-500 border-blue-500 text-white" : page === '...' ? "border-transparent cursor-default" : "border-neutral-300 dark:border-neutral-600 text-neutral-700 dark:text-neutral-300 hover:bg-neutral-50 dark:hover:bg-neutral-800" )} onClick={() => typeof page === 'number' && handlePageChange(page)} disabled={page === '...'} whileTap={{ scale: 0.95 }} initial={{ opacity: 0, y: -10 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: index * 0.05 }} > {page === '...' ? <FiMoreHorizontal className="w-4 h-4" /> : page} </motion.button> ))} {/* Next button */} <motion.button className={cn( "p-2 rounded-md border transition-all duration-200", currentPage === totalPages ? "border-neutral-200 dark:border-neutral-700 text-neutral-400 cursor-not-allowed" : "border-neutral-300 dark:border-neutral-600 text-neutral-700 dark:text-neutral-300 hover:bg-neutral-50 dark:hover:bg-neutral-800" )} onClick={() => handlePageChange(currentPage + 1)} disabled={currentPage === totalPages} whileTap={{ scale: 0.95 }} > <FiChevronRight className="w-4 h-4" /> </motion.button> </div> {/* Page info */} <div className="text-sm text-neutral-600 dark:text-neutral-400"> Page {currentPage} of {totalPages} </div> </div> </div> ); }; export default AdvancedPagination;
4

Update the import paths to match your project setup

Props

PropTypeDefaultDescription
currentPagenumber1The current active page number.
totalPagesnumber10The total number of pages.
onPageChangefunction() => {}Callback function when page changes.
showPageSizebooleantrueWhether to show the page size selector.