pagination.tsx raw

   1  import * as React from "react";
   2  import {
   3    ChevronLeftIcon,
   4    ChevronRightIcon,
   5    MoreHorizontalIcon,
   6  } from "lucide-react";
   7  
   8  import { cn } from "src/lib/utils";
   9  import { Button } from "src/components/ui/button";
  10  import { buttonVariants } from "src/components/ui/buttonVariants";
  11  
  12  function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
  13    return (
  14      <nav
  15        role="navigation"
  16        aria-label="pagination"
  17        data-slot="pagination"
  18        className={cn("mx-auto flex w-full justify-center", className)}
  19        {...props}
  20      />
  21    );
  22  }
  23  
  24  function PaginationContent({
  25    className,
  26    ...props
  27  }: React.ComponentProps<"ul">) {
  28    return (
  29      <ul
  30        data-slot="pagination-content"
  31        className={cn("flex flex-row items-center gap-1", className)}
  32        {...props}
  33      />
  34    );
  35  }
  36  
  37  function PaginationItem({ ...props }: React.ComponentProps<"li">) {
  38    return <li data-slot="pagination-item" {...props} />;
  39  }
  40  
  41  type PaginationLinkProps = {
  42    isActive?: boolean;
  43  } & Pick<React.ComponentProps<typeof Button>, "size"> &
  44    React.ComponentProps<"a">;
  45  
  46  function PaginationLink({
  47    className,
  48    isActive,
  49    size = "icon",
  50    ...props
  51  }: PaginationLinkProps) {
  52    return (
  53      <a
  54        aria-current={isActive ? "page" : undefined}
  55        data-slot="pagination-link"
  56        data-active={isActive}
  57        className={cn(
  58          buttonVariants({
  59            variant: isActive ? "outline" : "ghost",
  60            size,
  61          }),
  62          className
  63        )}
  64        {...props}
  65      />
  66    );
  67  }
  68  
  69  function PaginationPrevious({
  70    className,
  71    ...props
  72  }: React.ComponentProps<typeof PaginationLink>) {
  73    return (
  74      <PaginationLink
  75        aria-label="Go to previous page"
  76        size="default"
  77        className={cn("gap-1 px-2.5 sm:pl-2.5", className)}
  78        {...props}
  79      >
  80        <ChevronLeftIcon />
  81        <span className="hidden sm:block">Previous</span>
  82      </PaginationLink>
  83    );
  84  }
  85  
  86  function PaginationNext({
  87    className,
  88    ...props
  89  }: React.ComponentProps<typeof PaginationLink>) {
  90    return (
  91      <PaginationLink
  92        aria-label="Go to next page"
  93        size="default"
  94        className={cn("gap-1 px-2.5 sm:pr-2.5", className)}
  95        {...props}
  96      >
  97        <span className="hidden sm:block">Next</span>
  98        <ChevronRightIcon />
  99      </PaginationLink>
 100    );
 101  }
 102  
 103  function PaginationEllipsis({
 104    className,
 105    ...props
 106  }: React.ComponentProps<"span">) {
 107    return (
 108      <span
 109        aria-hidden
 110        data-slot="pagination-ellipsis"
 111        className={cn("flex size-9 items-center justify-center", className)}
 112        {...props}
 113      >
 114        <MoreHorizontalIcon className="size-4" />
 115        <span className="sr-only">More pages</span>
 116      </span>
 117    );
 118  }
 119  
 120  export {
 121    Pagination,
 122    PaginationContent,
 123    PaginationLink,
 124    PaginationItem,
 125    PaginationPrevious,
 126    PaginationNext,
 127    PaginationEllipsis,
 128  };
 129