dialog.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. "use client";
  2. import * as React from "react";
  3. import { XIcon } from "lucide-react";
  4. import { Dialog as DialogPrimitive } from "radix-ui";
  5. import { cn } from "@/lib/utils";
  6. import { Button } from "@/components/ui/button";
  7. function Dialog({
  8. ...props
  9. }: React.ComponentProps<typeof DialogPrimitive.Root>) {
  10. return <DialogPrimitive.Root data-slot="dialog" {...props} />;
  11. }
  12. function DialogTrigger({
  13. ...props
  14. }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
  15. return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
  16. }
  17. function DialogPortal({
  18. ...props
  19. }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
  20. return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
  21. }
  22. function DialogClose({
  23. ...props
  24. }: React.ComponentProps<typeof DialogPrimitive.Close>) {
  25. return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
  26. }
  27. function DialogOverlay({
  28. className,
  29. ...props
  30. }: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
  31. return (
  32. <DialogPrimitive.Overlay
  33. data-slot="dialog-overlay"
  34. className={cn(
  35. "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
  36. className,
  37. )}
  38. {...props}
  39. />
  40. );
  41. }
  42. function DialogContent({
  43. className,
  44. children,
  45. showCloseButton = true,
  46. ...props
  47. }: React.ComponentProps<typeof DialogPrimitive.Content> & {
  48. showCloseButton?: boolean;
  49. }) {
  50. return (
  51. <DialogPortal data-slot="dialog-portal">
  52. <DialogOverlay />
  53. <DialogPrimitive.Content
  54. data-slot="dialog-content"
  55. className={cn(
  56. "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 outline-none sm:max-w-lg",
  57. className,
  58. )}
  59. {...props}
  60. >
  61. {children}
  62. {showCloseButton && (
  63. <DialogPrimitive.Close
  64. data-slot="dialog-close"
  65. className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
  66. >
  67. <XIcon />
  68. <span className="sr-only">Close</span>
  69. </DialogPrimitive.Close>
  70. )}
  71. </DialogPrimitive.Content>
  72. </DialogPortal>
  73. );
  74. }
  75. function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
  76. return (
  77. <div
  78. data-slot="dialog-header"
  79. className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
  80. {...props}
  81. />
  82. );
  83. }
  84. function DialogFooter({
  85. className,
  86. showCloseButton = false,
  87. children,
  88. ...props
  89. }: React.ComponentProps<"div"> & {
  90. showCloseButton?: boolean;
  91. }) {
  92. return (
  93. <div
  94. data-slot="dialog-footer"
  95. className={cn(
  96. "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
  97. className,
  98. )}
  99. {...props}
  100. >
  101. {children}
  102. {showCloseButton && (
  103. <DialogPrimitive.Close asChild>
  104. <Button variant="outline">Close</Button>
  105. </DialogPrimitive.Close>
  106. )}
  107. </div>
  108. );
  109. }
  110. function DialogTitle({
  111. className,
  112. ...props
  113. }: React.ComponentProps<typeof DialogPrimitive.Title>) {
  114. return (
  115. <DialogPrimitive.Title
  116. data-slot="dialog-title"
  117. className={cn("text-lg leading-none font-semibold", className)}
  118. {...props}
  119. />
  120. );
  121. }
  122. function DialogDescription({
  123. className,
  124. ...props
  125. }: React.ComponentProps<typeof DialogPrimitive.Description>) {
  126. return (
  127. <DialogPrimitive.Description
  128. data-slot="dialog-description"
  129. className={cn("text-muted-foreground text-sm", className)}
  130. {...props}
  131. />
  132. );
  133. }
  134. export {
  135. Dialog,
  136. DialogClose,
  137. DialogContent,
  138. DialogDescription,
  139. DialogFooter,
  140. DialogHeader,
  141. DialogOverlay,
  142. DialogPortal,
  143. DialogTitle,
  144. DialogTrigger,
  145. };