pagination.tsx 2.6 KB

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