|
1 | | -import * as DialogPrimitive from "@radix-ui/react-dialog"; |
| 1 | +"use client"; |
| 2 | + |
| 3 | +import { Dialog as DialogPrimitive } from "@base-ui/react/dialog"; |
2 | 4 | import { XIcon } from "lucide-react"; |
3 | | -import * as React from "react"; |
| 5 | +import type * as React from "react"; |
4 | 6 |
|
5 | 7 | import { cn } from "~/lib/utils"; |
6 | 8 |
|
7 | | -function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) { |
8 | | - return <DialogPrimitive.Root data-slot="dialog" {...props} />; |
9 | | -} |
| 9 | +const DialogCreateHandle = DialogPrimitive.createHandle; |
| 10 | + |
| 11 | +const Dialog = DialogPrimitive.Root; |
| 12 | + |
| 13 | +const DialogPortal = DialogPrimitive.Portal; |
10 | 14 |
|
11 | | -function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) { |
| 15 | +function DialogTrigger(props: DialogPrimitive.Trigger.Props) { |
12 | 16 | return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />; |
13 | 17 | } |
14 | 18 |
|
15 | | -function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) { |
16 | | - return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />; |
| 19 | +function DialogClose(props: DialogPrimitive.Close.Props) { |
| 20 | + return <DialogPrimitive.Close data-slot="dialog-close" {...props} />; |
17 | 21 | } |
18 | 22 |
|
19 | | -function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) { |
20 | | - return <DialogPrimitive.Close data-slot="dialog-close" {...props} />; |
| 23 | +function DialogBackdrop({ className, ...props }: DialogPrimitive.Backdrop.Props) { |
| 24 | + return ( |
| 25 | + <DialogPrimitive.Backdrop |
| 26 | + className={cn( |
| 27 | + "fixed inset-0 z-50 bg-[radial-gradient(circle_at_top,rgba(96,165,250,0.12),transparent_38%),rgba(3,7,18,0.82)] backdrop-blur-sm transition-all duration-200 data-ending-style:opacity-0 data-starting-style:opacity-0", |
| 28 | + className, |
| 29 | + )} |
| 30 | + data-slot="dialog-backdrop" |
| 31 | + {...props} |
| 32 | + /> |
| 33 | + ); |
21 | 34 | } |
22 | 35 |
|
23 | | -function DialogOverlay({ |
24 | | - className, |
25 | | - ...props |
26 | | -}: React.ComponentProps<typeof DialogPrimitive.Overlay>) { |
| 36 | +function DialogViewport({ className, ...props }: DialogPrimitive.Viewport.Props) { |
27 | 37 | return ( |
28 | | - <DialogPrimitive.Overlay |
29 | | - data-slot="dialog-overlay" |
| 38 | + <DialogPrimitive.Viewport |
30 | 39 | className={cn( |
31 | | - "fixed inset-0 z-50 bg-[radial-gradient(circle_at_top,rgba(96,165,250,0.12),transparent_38%),rgba(3,7,18,0.82)] backdrop-blur-sm", |
32 | | - "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", |
| 40 | + "fixed inset-0 z-50 grid grid-rows-[1fr_auto_1fr] justify-items-center p-4", |
33 | 41 | className, |
34 | 42 | )} |
| 43 | + data-slot="dialog-viewport" |
35 | 44 | {...props} |
36 | 45 | /> |
37 | 46 | ); |
38 | 47 | } |
39 | 48 |
|
40 | | -function DialogContent({ |
| 49 | +function DialogPopup({ |
41 | 50 | className, |
42 | 51 | children, |
43 | 52 | showCloseButton = true, |
44 | 53 | ...props |
45 | | -}: React.ComponentProps<typeof DialogPrimitive.Content> & { showCloseButton?: boolean }) { |
| 54 | +}: DialogPrimitive.Popup.Props & { |
| 55 | + showCloseButton?: boolean; |
| 56 | +}) { |
46 | 57 | return ( |
47 | | - <DialogPortal data-slot="dialog-portal"> |
48 | | - <DialogOverlay /> |
49 | | - <DialogPrimitive.Content |
50 | | - data-slot="dialog-content" |
51 | | - className={cn( |
52 | | - "fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-2xl border border-border/80 bg-card/94 p-6 text-card-foreground shadow-[0_40px_120px_-45px_hsl(220_80%_2%/0.98)] backdrop-blur-2xl duration-200 sm:max-w-lg", |
53 | | - "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", |
54 | | - className, |
55 | | - )} |
56 | | - {...props} |
57 | | - > |
58 | | - {children} |
59 | | - {showCloseButton && ( |
60 | | - <DialogPrimitive.Close className="absolute top-4 right-4 rounded-lg p-1.5 text-muted-foreground/75 transition-colors hover:bg-accent/80 hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/70 focus-visible:ring-offset-2 focus-visible:ring-offset-card"> |
61 | | - <XIcon className="size-4" /> |
62 | | - <span className="sr-only">Close</span> |
63 | | - </DialogPrimitive.Close> |
64 | | - )} |
65 | | - </DialogPrimitive.Content> |
| 58 | + <DialogPortal> |
| 59 | + <DialogBackdrop /> |
| 60 | + <DialogViewport> |
| 61 | + <DialogPrimitive.Popup |
| 62 | + className={cn( |
| 63 | + "-translate-y-[calc(1.25rem*var(--nested-dialogs))] relative row-start-2 flex max-h-full min-h-0 w-full min-w-0 max-w-lg scale-[calc(1-0.1*var(--nested-dialogs))] flex-col rounded-2xl border border-border/80 bg-card/94 text-card-foreground opacity-[calc(1-0.1*var(--nested-dialogs))] shadow-[0_40px_120px_-45px_hsl(220_80%_2%/0.98)] outline-none backdrop-blur-2xl transition-[scale,opacity,translate] duration-200 ease-in-out will-change-transform before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] data-nested:data-ending-style:translate-y-8 data-nested:data-starting-style:translate-y-8 data-nested-dialog-open:origin-top data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]", |
| 64 | + className, |
| 65 | + )} |
| 66 | + data-slot="dialog-popup" |
| 67 | + {...props} |
| 68 | + > |
| 69 | + {children} |
| 70 | + {showCloseButton && ( |
| 71 | + <DialogPrimitive.Close className="absolute top-4 right-4 rounded-lg p-1.5 text-muted-foreground/75 transition-colors hover:bg-accent/80 hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/70 focus-visible:ring-offset-2 focus-visible:ring-offset-card"> |
| 72 | + <XIcon className="size-4" /> |
| 73 | + <span className="sr-only">Close</span> |
| 74 | + </DialogPrimitive.Close> |
| 75 | + )} |
| 76 | + </DialogPrimitive.Popup> |
| 77 | + </DialogViewport> |
66 | 78 | </DialogPortal> |
67 | 79 | ); |
68 | 80 | } |
69 | 81 |
|
70 | 82 | function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { |
71 | 83 | return ( |
72 | 84 | <div |
| 85 | + className={cn("flex flex-col gap-2 px-6 pt-6 text-center sm:text-left", className)} |
73 | 86 | data-slot="dialog-header" |
74 | | - className={cn("flex flex-col gap-2 text-center sm:text-left", className)} |
75 | 87 | {...props} |
76 | 88 | /> |
77 | 89 | ); |
78 | 90 | } |
79 | 91 |
|
80 | | -function DialogFooter({ className, ...props }: React.ComponentProps<"div">) { |
| 92 | +function DialogPanel({ className, ...props }: React.ComponentProps<"div">) { |
| 93 | + return <div className={cn("px-6 pb-6", className)} data-slot="dialog-panel" {...props} />; |
| 94 | +} |
| 95 | + |
| 96 | +function DialogFooter({ |
| 97 | + className, |
| 98 | + variant = "default", |
| 99 | + ...props |
| 100 | +}: React.ComponentProps<"div"> & { |
| 101 | + variant?: "default" | "bare"; |
| 102 | +}) { |
81 | 103 | return ( |
82 | 104 | <div |
| 105 | + className={cn( |
| 106 | + "flex flex-col-reverse gap-2 px-6 sm:flex-row sm:justify-end", |
| 107 | + variant === "default" && |
| 108 | + "rounded-b-[calc(var(--radius-2xl)-1px)] border-t bg-muted/72 py-4", |
| 109 | + variant === "bare" && "pb-6", |
| 110 | + className, |
| 111 | + )} |
83 | 112 | data-slot="dialog-footer" |
84 | | - className={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)} |
85 | 113 | {...props} |
86 | 114 | /> |
87 | 115 | ); |
88 | 116 | } |
89 | 117 |
|
90 | | -function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) { |
| 118 | +function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) { |
91 | 119 | return ( |
92 | 120 | <DialogPrimitive.Title |
93 | | - data-slot="dialog-title" |
94 | 121 | className={cn("text-lg leading-none font-semibold tracking-tight", className)} |
| 122 | + data-slot="dialog-title" |
95 | 123 | {...props} |
96 | 124 | /> |
97 | 125 | ); |
98 | 126 | } |
99 | 127 |
|
100 | | -function DialogDescription({ |
101 | | - className, |
102 | | - ...props |
103 | | -}: React.ComponentProps<typeof DialogPrimitive.Description>) { |
| 128 | +function DialogDescription({ className, ...props }: DialogPrimitive.Description.Props) { |
104 | 129 | return ( |
105 | 130 | <DialogPrimitive.Description |
106 | | - data-slot="dialog-description" |
107 | 131 | className={cn("text-sm leading-6 text-muted-foreground", className)} |
| 132 | + data-slot="dialog-description" |
108 | 133 | {...props} |
109 | 134 | /> |
110 | 135 | ); |
111 | 136 | } |
112 | 137 |
|
113 | 138 | export { |
| 139 | + DialogCreateHandle, |
114 | 140 | Dialog, |
| 141 | + DialogBackdrop, |
| 142 | + DialogBackdrop as DialogOverlay, |
115 | 143 | DialogClose, |
116 | | - DialogContent, |
117 | 144 | DialogDescription, |
118 | 145 | DialogFooter, |
119 | 146 | DialogHeader, |
120 | | - DialogOverlay, |
| 147 | + DialogPanel, |
| 148 | + DialogPopup, |
| 149 | + DialogPopup as DialogContent, |
121 | 150 | DialogPortal, |
122 | 151 | DialogTitle, |
123 | 152 | DialogTrigger, |
| 153 | + DialogViewport, |
124 | 154 | }; |
0 commit comments