dialog.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. "use client"
  2. import * as React from "react"
  3. import { Dialog as DialogPrimitive } from "@base-ui/react/dialog"
  4. import { X } from "lucide-react"
  5. import { cn } from "@/lib/utils/client"
  6. const Dialog = DialogPrimitive.Root
  7. const DialogTrigger = React.forwardRef<
  8. HTMLButtonElement,
  9. React.ComponentPropsWithoutRef<typeof DialogPrimitive.Trigger> & { asChild?: boolean }
  10. >(({ asChild, children, ...props }, ref) => {
  11. if (asChild) {
  12. return <DialogPrimitive.Trigger ref={ref} render={children as React.ReactElement} {...props} />
  13. }
  14. return <DialogPrimitive.Trigger ref={ref} {...props}>{children}</DialogPrimitive.Trigger>
  15. })
  16. DialogTrigger.displayName = "DialogTrigger"
  17. const DialogPortal = DialogPrimitive.Portal
  18. const DialogClose = React.forwardRef<
  19. HTMLButtonElement,
  20. React.ComponentPropsWithoutRef<typeof DialogPrimitive.Close> & { asChild?: boolean }
  21. >(({ asChild, children, ...props }, ref) => {
  22. if (asChild) {
  23. return <DialogPrimitive.Close ref={ref} render={children as React.ReactElement} {...props} />
  24. }
  25. return <DialogPrimitive.Close ref={ref} {...props}>{children}</DialogPrimitive.Close>
  26. })
  27. DialogClose.displayName = "DialogClose"
  28. const DialogOverlay = React.forwardRef<
  29. HTMLDivElement,
  30. React.ComponentPropsWithoutRef<typeof DialogPrimitive.Backdrop>
  31. >(({ className, ...props }, ref) => (
  32. <DialogPrimitive.Backdrop
  33. ref={ref}
  34. className={cn(
  35. "fixed inset-0 z-50 bg-black/80 data-[open]:animate-in data-[closed]:animate-out data-[closed]:fade-out-0 data-[open]:fade-in-0",
  36. className
  37. )}
  38. {...props}
  39. />
  40. ))
  41. DialogOverlay.displayName = "DialogOverlay"
  42. const DialogContent = React.forwardRef<
  43. HTMLDivElement,
  44. React.ComponentPropsWithoutRef<typeof DialogPrimitive.Popup>
  45. >(({ className, children, ...props }, ref) => (
  46. <DialogPortal>
  47. <DialogOverlay />
  48. <DialogPrimitive.Popup
  49. ref={ref}
  50. className={cn(
  51. "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[open]:animate-in data-[closed]:animate-out data-[closed]:fade-out-0 data-[open]:fade-in-0 data-[closed]:zoom-out-95 data-[open]:zoom-in-95 data-[closed]:slide-out-to-left-1/2 data-[closed]:slide-out-to-top-[48%] data-[open]:slide-in-from-left-1/2 data-[open]:slide-in-from-top-[48%] sm:rounded-lg",
  52. className
  53. )}
  54. {...props}
  55. >
  56. {children}
  57. <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[open]:bg-accent data-[open]:text-muted-foreground">
  58. <X className="h-4 w-4" />
  59. <span className="sr-only">Close</span>
  60. </DialogPrimitive.Close>
  61. </DialogPrimitive.Popup>
  62. </DialogPortal>
  63. ))
  64. DialogContent.displayName = "DialogContent"
  65. const DialogHeader = ({
  66. className,
  67. ...props
  68. }: React.HTMLAttributes<HTMLDivElement>) => (
  69. <div
  70. className={cn(
  71. "flex flex-col space-y-1.5 text-center sm:text-left",
  72. className
  73. )}
  74. {...props}
  75. />
  76. )
  77. DialogHeader.displayName = "DialogHeader"
  78. const DialogFooter = ({
  79. className,
  80. ...props
  81. }: React.HTMLAttributes<HTMLDivElement>) => (
  82. <div
  83. className={cn(
  84. "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
  85. className
  86. )}
  87. {...props}
  88. />
  89. )
  90. DialogFooter.displayName = "DialogFooter"
  91. const DialogTitle = React.forwardRef<
  92. HTMLHeadingElement,
  93. React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
  94. >(({ className, ...props }, ref) => (
  95. <DialogPrimitive.Title
  96. ref={ref}
  97. className={cn(
  98. "text-lg font-semibold leading-none tracking-tight pb-2",
  99. className
  100. )}
  101. {...props}
  102. />
  103. ))
  104. DialogTitle.displayName = "DialogTitle"
  105. const DialogDescription = React.forwardRef<
  106. HTMLParagraphElement,
  107. React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description> & { asChild?: boolean }
  108. >(({ className, asChild, children, ...props }, ref) => {
  109. if (asChild) {
  110. return <DialogPrimitive.Description ref={ref} className={cn("text-sm text-muted-foreground", className)} render={children as React.ReactElement} {...props} />
  111. }
  112. return (
  113. <DialogPrimitive.Description
  114. ref={ref}
  115. className={cn("text-sm text-muted-foreground", className)}
  116. {...props}
  117. >{children}</DialogPrimitive.Description>
  118. )
  119. })
  120. DialogDescription.displayName = "DialogDescription"
  121. export {
  122. Dialog,
  123. DialogPortal,
  124. DialogOverlay,
  125. DialogTrigger,
  126. DialogClose,
  127. DialogContent,
  128. DialogHeader,
  129. DialogFooter,
  130. DialogTitle,
  131. DialogDescription,
  132. }