summaryrefslogtreecommitdiff
path: root/jb-ui/src/components/ui/pagination.tsx
diff options
context:
space:
mode:
authorMax Nanis2026-02-18 20:42:03 -0500
committerMax Nanis2026-02-18 20:42:03 -0500
commit3eaa56f0306ead818f64c3d99fc6d230d9b970a4 (patch)
tree9fecc2f1456e6321572e0e65f57106916df173e2 /jb-ui/src/components/ui/pagination.tsx
downloadamt-jb-3eaa56f0306ead818f64c3d99fc6d230d9b970a4.tar.gz
amt-jb-3eaa56f0306ead818f64c3d99fc6d230d9b970a4.zip
HERE WE GO, HERE WE GO, HERE WE GO
Diffstat (limited to 'jb-ui/src/components/ui/pagination.tsx')
-rw-r--r--jb-ui/src/components/ui/pagination.tsx127
1 files changed, 127 insertions, 0 deletions
diff --git a/jb-ui/src/components/ui/pagination.tsx b/jb-ui/src/components/ui/pagination.tsx
new file mode 100644
index 0000000..1dcfb0c
--- /dev/null
+++ b/jb-ui/src/components/ui/pagination.tsx
@@ -0,0 +1,127 @@
+import * as React from "react"
+import {
+ ChevronLeftIcon,
+ ChevronRightIcon,
+ MoreHorizontalIcon,
+} from "lucide-react"
+
+import { cn } from "@/lib/utils"
+import { buttonVariants, type Button } from "@/components/ui/button"
+
+function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
+ return (
+ <nav
+ role="navigation"
+ aria-label="pagination"
+ data-slot="pagination"
+ className={cn("mx-auto flex w-full justify-center", className)}
+ {...props}
+ />
+ )
+}
+
+function PaginationContent({
+ className,
+ ...props
+}: React.ComponentProps<"ul">) {
+ return (
+ <ul
+ data-slot="pagination-content"
+ className={cn("flex flex-row items-center gap-1", className)}
+ {...props}
+ />
+ )
+}
+
+function PaginationItem({ ...props }: React.ComponentProps<"li">) {
+ return <li data-slot="pagination-item" {...props} />
+}
+
+type PaginationLinkProps = {
+ isActive?: boolean
+} & Pick<React.ComponentProps<typeof Button>, "size"> &
+ React.ComponentProps<"a">
+
+function PaginationLink({
+ className,
+ isActive,
+ size = "icon",
+ ...props
+}: PaginationLinkProps) {
+ return (
+ <a
+ aria-current={isActive ? "page" : undefined}
+ data-slot="pagination-link"
+ data-active={isActive}
+ className={cn(
+ buttonVariants({
+ variant: isActive ? "outline" : "ghost",
+ size,
+ }),
+ className
+ )}
+ {...props}
+ />
+ )
+}
+
+function PaginationPrevious({
+ className,
+ ...props
+}: React.ComponentProps<typeof PaginationLink>) {
+ return (
+ <PaginationLink
+ aria-label="Go to previous page"
+ size="default"
+ className={cn("gap-1 px-2.5 sm:pl-2.5", className)}
+ {...props}
+ >
+ <ChevronLeftIcon />
+ <span className="hidden sm:block">Previous</span>
+ </PaginationLink>
+ )
+}
+
+function PaginationNext({
+ className,
+ ...props
+}: React.ComponentProps<typeof PaginationLink>) {
+ return (
+ <PaginationLink
+ aria-label="Go to next page"
+ size="default"
+ className={cn("gap-1 px-2.5 sm:pr-2.5", className)}
+ {...props}
+ >
+ <span className="hidden sm:block">Next</span>
+ <ChevronRightIcon />
+ </PaginationLink>
+ )
+}
+
+function PaginationEllipsis({
+ className,
+ ...props
+}: React.ComponentProps<"span">) {
+ return (
+ <span
+ aria-hidden
+ data-slot="pagination-ellipsis"
+ className={cn("flex size-9 items-center justify-center", className)}
+ {...props}
+ >
+ <MoreHorizontalIcon className="size-4" />
+ <span className="sr-only">More pages</span>
+ </span>
+ )
+}
+
+export {
+ Pagination,
+ PaginationContent,
+ PaginationLink,
+ PaginationItem,
+ PaginationPrevious,
+ PaginationNext,
+ PaginationEllipsis,
+}