Dialog
A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.
import { styled } from "styled-system/jsx";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
export default function DialogDemo() {
return (
<Dialog>
<form>
<DialogTrigger asChild>
<Button variant="outline">Open Dialog</Button>
</DialogTrigger>
<DialogContent css={{ sm: { maxW: "425px" } }}>
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogDescription>
Make changes to your profile here. Click save when you're done.
</DialogDescription>
</DialogHeader>
<styled.div css={{ display: "grid", gap: "4" }}>
<styled.div css={{ display: "grid", gap: "3" }}>
<Label htmlFor="name-1">Name</Label>
<Input id="name-1" name="name" defaultValue="Pedro Duarte" />
</styled.div>
<styled.div css={{ display: "grid", gap: "3" }}>
<Label htmlFor="username-1">Username</Label>
<Input id="username-1" name="username" defaultValue="@peduarte" />
</styled.div>
</styled.div>
<DialogFooter>
<DialogClose asChild>
<Button variant="outline">Cancel</Button>
</DialogClose>
<Button type="submit">Save changes</Button>
</DialogFooter>
</DialogContent>
</form>
</Dialog>
);
}
Installation
npx nore-ui-cli@latest add dialogUsage
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
<Dialog>
<DialogTrigger>Open</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you absolutely sure?</DialogTitle>
<DialogDescription>
This action cannot be undone. This will permanently delete your account and remove your data
from our servers.
</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>
Examples
Dialog Custom Close Button
import { styled } from "styled-system/jsx";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
export default function DialogCloseButton() {
return (
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">Share</Button>
</DialogTrigger>
<DialogContent css={{ sm: { maxW: "md" } }}>
<DialogHeader>
<DialogTitle>Share link</DialogTitle>
<DialogDescription>Anyone who has this link will be able to view this.</DialogDescription>
</DialogHeader>
<styled.div css={{ display: "flex", alignItems: "center", gap: "2" }}>
<styled.div css={{ display: "grid", flex: "1", gap: "2" }}>
<Label htmlFor="link" css={{ srOnly: true }}>
Link
</Label>
<Input id="link" defaultValue="https://ui.shadcn.com/docs/installation" readOnly />
</styled.div>
</styled.div>
<DialogFooter css={{ sm: { justifyContent: "flex-start" } }}>
<DialogClose asChild>
<Button type="button" variant="secondary">
Close
</Button>
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
Responsive Dialog
You can make the dialog become a drawer on smaller screens by using this recipe.
preset/slot-recipes/dialog-responsive.ts
import { defineSlotRecipe } from "@pandacss/dev";
export const dialogSlotRecipe = defineSlotRecipe({
className: "dialog",
slots: [
"root",
"trigger",
"portal",
"overlay",
"header",
"title",
"description",
"content",
"footer",
"close",
],
base: {
overlay: {
pos: "fixed",
inset: "0",
zIndex: "50",
bg: "bg/80",
_open: {
animateIn: true,
fadeIn: "0",
},
_closed: {
animateOut: true,
fadeOut: "0",
},
},
header: {
display: "flex",
flexDir: "column",
spaceY: "1.5",
},
title: {
textStyle: "lg",
fontWeight: "semibold",
lineHeight: "none",
letterSpacing: "tight",
},
description: {
textStyle: "sm",
color: "fg.muted",
},
content: {
pos: "fixed",
bottom: "0",
left: "0",
zIndex: "50",
display: "grid",
w: "full",
maxW: "full",
gap: "4",
borderWidth: "1px",
bg: "bg",
p: "6",
roundedTop: "md",
shadow: "lg",
_open: {
animateIn: true,
fadeIn: "0",
slideInFromBottom: "100%",
},
_closed: {
animateOut: true,
fadeOut: "0",
slideOutToBottom: "100%",
},
md: {
maxW: "lg",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
bottom: "auto",
rounded: "md",
_open: {
slideInFromBottom: "0",
zoomIn: "95",
slideInFromLeft: "50%",
slideInFromTop: "48%",
},
_closed: {
slideOutToBottom: "0",
zoomOut: "95",
slideOutToLeft: "50%",
slideOutToTop: "48%",
},
},
},
footer: {
display: "flex",
flexDir: "column-reverse",
sm: {
flexDir: "row",
justifyContent: "flex-end",
gap: "2",
},
},
},
});