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