Skip to content

Commit aa492e3

Browse files
authored
feat: add dialog component (#31)
1 parent 800c3cc commit aa492e3

File tree

3 files changed

+204
-2
lines changed

3 files changed

+204
-2
lines changed

package-lock.json

Lines changed: 60 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"dependencies": {
1818
"@hookform/resolvers": "^5.2.2",
1919
"@prisma/client": "^6.15.0",
20+
"@radix-ui/react-dialog": "^1.1.15",
2021
"@radix-ui/react-label": "^2.1.7",
2122
"@radix-ui/react-select": "^2.2.6",
2223
"@radix-ui/react-slot": "^1.2.3",

src/components/ui/dialog.tsx

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
"use client"
2+
3+
import * as React from "react"
4+
import * as DialogPrimitive from "@radix-ui/react-dialog"
5+
import { XIcon } from "lucide-react"
6+
7+
import { cn } from "@/lib/utils"
8+
9+
function Dialog({
10+
...props
11+
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
12+
return <DialogPrimitive.Root data-slot="dialog" {...props} />
13+
}
14+
15+
function DialogTrigger({
16+
...props
17+
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
18+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
19+
}
20+
21+
function DialogPortal({
22+
...props
23+
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
24+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
25+
}
26+
27+
function DialogClose({
28+
...props
29+
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
30+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
31+
}
32+
33+
function DialogOverlay({
34+
className,
35+
...props
36+
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
37+
return (
38+
<DialogPrimitive.Overlay
39+
data-slot="dialog-overlay"
40+
className={cn(
41+
"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",
42+
className
43+
)}
44+
{...props}
45+
/>
46+
)
47+
}
48+
49+
function DialogContent({
50+
className,
51+
children,
52+
showCloseButton = true,
53+
...props
54+
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
55+
showCloseButton?: boolean
56+
}) {
57+
return (
58+
<DialogPortal data-slot="dialog-portal">
59+
<DialogOverlay />
60+
<DialogPrimitive.Content
61+
data-slot="dialog-content"
62+
className={cn(
63+
"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 sm:max-w-lg",
64+
className
65+
)}
66+
{...props}
67+
>
68+
{children}
69+
{showCloseButton && (
70+
<DialogPrimitive.Close
71+
data-slot="dialog-close"
72+
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"
73+
>
74+
<XIcon />
75+
<span className="sr-only">Close</span>
76+
</DialogPrimitive.Close>
77+
)}
78+
</DialogPrimitive.Content>
79+
</DialogPortal>
80+
)
81+
}
82+
83+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
84+
return (
85+
<div
86+
data-slot="dialog-header"
87+
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
88+
{...props}
89+
/>
90+
)
91+
}
92+
93+
function DialogFooter({ className, ...props }: React.ComponentProps<"div">) {
94+
return (
95+
<div
96+
data-slot="dialog-footer"
97+
className={cn(
98+
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
99+
className
100+
)}
101+
{...props}
102+
/>
103+
)
104+
}
105+
106+
function DialogTitle({
107+
className,
108+
...props
109+
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
110+
return (
111+
<DialogPrimitive.Title
112+
data-slot="dialog-title"
113+
className={cn("text-lg leading-none font-semibold", className)}
114+
{...props}
115+
/>
116+
)
117+
}
118+
119+
function DialogDescription({
120+
className,
121+
...props
122+
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
123+
return (
124+
<DialogPrimitive.Description
125+
data-slot="dialog-description"
126+
className={cn("text-muted-foreground text-sm", className)}
127+
{...props}
128+
/>
129+
)
130+
}
131+
132+
export {
133+
Dialog,
134+
DialogClose,
135+
DialogContent,
136+
DialogDescription,
137+
DialogFooter,
138+
DialogHeader,
139+
DialogOverlay,
140+
DialogPortal,
141+
DialogTitle,
142+
DialogTrigger,
143+
}

0 commit comments

Comments
 (0)