← full-stack-fastapi-template  /  frontend/src/components/ui/pagination.tsx

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