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