dialog.tsx
1 "use client" 2 import * as React from "react" 3 import * as DialogPrimitive from "@radix-ui/react-dialog" 4 import { X } from "lucide-react" 5 import { cn } from "@/lib/utils" 6 7 const Dialog = DialogPrimitive.Root 8 9 const DialogTrigger = DialogPrimitive.Trigger 10 11 const DialogPortal = DialogPrimitive.Portal 12 13 const DialogClose = DialogPrimitive.Close 14 15 const DialogOverlay = React.forwardRef< 16 React.ElementRef<typeof DialogPrimitive.Overlay>, 17 React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay> 18 >(({ className, ...props }, ref) => ( 19 <DialogPrimitive.Overlay 20 ref={ref} 21 className={cn( 22 "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", 23 className 24 )} 25 {...props} 26 /> 27 )) 28 DialogOverlay.displayName = DialogPrimitive.Overlay.displayName 29 30 const DialogContent = React.forwardRef< 31 React.ElementRef<typeof DialogPrimitive.Content>, 32 React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> 33 >(({ className, children, ...props }, ref) => ( 34 <DialogPortal> 35 <DialogOverlay /> 36 <DialogPrimitive.Content 37 ref={ref} 38 className={cn( 39 "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-[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 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg", 40 className 41 )} 42 {...props} 43 > 44 {children} 45 <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-[state=open]:bg-accent data-[state=open]:text-muted-foreground"> 46 <X className="h-4 w-4" /> 47 <span className="sr-only">Close</span> 48 </DialogPrimitive.Close> 49 </DialogPrimitive.Content> 50 </DialogPortal> 51 )) 52 DialogContent.displayName = DialogPrimitive.Content.displayName 53 54 const DialogHeader = ({ 55 className, 56 ...props 57 }: React.HTMLAttributes<HTMLDivElement>) => ( 58 <div 59 className={cn( 60 "flex flex-col space-y-1.5 text-center sm:text-left", 61 className 62 )} 63 {...props} 64 /> 65 ) 66 DialogHeader.displayName = "DialogHeader" 67 68 const DialogFooter = ({ 69 className, 70 ...props 71 }: React.HTMLAttributes<HTMLDivElement>) => ( 72 <div 73 className={cn( 74 "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", 75 className 76 )} 77 {...props} 78 /> 79 ) 80 DialogFooter.displayName = "DialogFooter" 81 82 const DialogTitle = React.forwardRef< 83 React.ElementRef<typeof DialogPrimitive.Title>, 84 React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title> 85 >(({ className, ...props }, ref) => ( 86 <DialogPrimitive.Title 87 ref={ref} 88 className={cn( 89 "text-lg font-semibold leading-none tracking-tight", 90 className 91 )} 92 {...props} 93 /> 94 )) 95 DialogTitle.displayName = DialogPrimitive.Title.displayName 96 97 const DialogDescription = React.forwardRef< 98 React.ElementRef<typeof DialogPrimitive.Description>, 99 React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description> 100 >(({ className, ...props }, ref) => ( 101 <DialogPrimitive.Description 102 ref={ref} 103 className={cn("text-sm text-muted-foreground", className)} 104 {...props} 105 /> 106 )) 107 DialogDescription.displayName = DialogPrimitive.Description.displayName 108 109 export { 110 Dialog, 111 DialogPortal, 112 DialogOverlay, 113 DialogClose, 114 DialogTrigger, 115 DialogContent, 116 DialogHeader, 117 DialogFooter, 118 DialogTitle, 119 DialogDescription, 120 }