pagination.tsx 2.6 KB

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