Components
Dialog
Modal dialog for focused user interactions. Built on Radix UI.
Import
import {
Dialog,
DialogTrigger,
DialogContent,
DialogHeader,
DialogTitle,
DialogDescription,
DialogFooter,
DialogClose,
} from '@framingui/ui';Basic Usage
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Dialog Title</DialogTitle>
<DialogDescription>
This is the dialog description.
</DialogDescription>
</DialogHeader>
<p>Dialog content goes here.</p>
</DialogContent>
</Dialog>With Footer Actions
<Dialog>
<DialogTrigger asChild>
<Button>Edit Profile</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Edit Profile</DialogTitle>
<DialogDescription>
Make changes to your profile here.
</DialogDescription>
</DialogHeader>
<div className="space-y-4 py-4">
<div className="space-y-2">
<Label htmlFor="name">Name</Label>
<Input id="name" defaultValue="John Doe" />
</div>
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" defaultValue="john@example.com" />
</div>
</div>
<DialogFooter>
<DialogClose asChild>
<Button variant="outline">Cancel</Button>
</DialogClose>
<Button>Save Changes</Button>
</DialogFooter>
</DialogContent>
</Dialog>Controlled Dialog
function ControlledDialog() {
const [open, setOpen] = useState(false);
const handleSave = async () => {
await saveData();
setOpen(false);
};
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button>Open</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Save Changes?</DialogTitle>
</DialogHeader>
<DialogFooter>
<Button variant="outline" onClick={() => setOpen(false)}>
Cancel
</Button>
<Button onClick={handleSave}>Save</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}Confirmation Dialog
<Dialog>
<DialogTrigger asChild>
<Button variant="destructive">Delete Account</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you sure?</DialogTitle>
<DialogDescription>
This action cannot be undone. This will permanently delete your
account and remove your data from our servers.
</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose asChild>
<Button variant="outline">Cancel</Button>
</DialogClose>
<Button variant="destructive">Delete Account</Button>
</DialogFooter>
</DialogContent>
</Dialog>Form Inside Dialog
function CreateProjectDialog() {
const [open, setOpen] = useState(false);
const onSubmit = async (data) => {
await createProject(data);
setOpen(false);
};
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button>
<Plus className="w-4 h-4 mr-2" />
New Project
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-md">
<form onSubmit={handleSubmit(onSubmit)}>
<DialogHeader>
<DialogTitle>Create Project</DialogTitle>
<DialogDescription>
Add a new project to your workspace.
</DialogDescription>
</DialogHeader>
<div className="space-y-4 py-4">
<div className="space-y-2">
<Label htmlFor="project-name">Project Name</Label>
<Input id="project-name" placeholder="My awesome project" />
</div>
<div className="space-y-2">
<Label htmlFor="description">Description</Label>
<Textarea id="description" placeholder="What's this project about?" />
</div>
</div>
<DialogFooter>
<Button type="submit">Create Project</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
);
}Custom Width
// Small <DialogContent className="sm:max-w-sm">...</DialogContent> // Medium (default) <DialogContent className="sm:max-w-md">...</DialogContent> // Large <DialogContent className="sm:max-w-lg">...</DialogContent> // Extra large <DialogContent className="sm:max-w-xl">...</DialogContent> // Full width (mobile-like) <DialogContent className="sm:max-w-full sm:h-full sm:rounded-none"> ... </DialogContent>
Props
| Component | Prop | Description |
|---|---|---|
| Dialog | open | Controlled open state |
| Dialog | onOpenChange | Callback when open state changes |
| DialogTrigger | asChild | Render as child element |