pagination.tsx 2.7 KB

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