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