Dialogs & Overlays
Modal dialogs, drawers, popovers, and overlay components.
Use Dialog for focused modal interactions, AlertDialog for destructive action confirmations, Drawer or Sheet for slide-out panels, Popover for anchored floating content, and DropdownMenu/ContextMenu for action menus. All overlay components handle focus trapping, keyboard navigation, and backdrop clicks.
This guide is part of the UI Components documentation.
Overlay components are UI elements that appear above the main content layer, capturing user attention for focused interactions while maintaining context through backdrop dimming and focus management.
- Use Dialog when: displaying forms, settings, or content that needs focus. - Use AlertDialog when: confirming destructive actions (delete, cancel subscription).
- Use Drawer/Sheet when: showing secondary content that doesn't block the main view.
- Use Popover when: providing contextual info anchored to an element.
- If unsure: Dialog for forms, AlertDialog for deletions.
Dialog
Modal dialog for focused interactions.
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose } from '@kit/ui/dialog';<Dialog> <DialogTrigger asChild> <Button>Open Dialog</Button> </DialogTrigger> <DialogContent> <DialogHeader> <DialogTitle>Dialog Title</DialogTitle> <DialogDescription> This is a description of the dialog content. </DialogDescription> </DialogHeader> <div className="py-4"> Dialog body content </div> <DialogFooter> <DialogClose asChild> <Button variant="outline">Cancel</Button> </DialogClose> <Button>Confirm</Button> </DialogFooter> </DialogContent></Dialog>Controlled Dialog
const [open, setOpen] = useState(false);<Dialog open={open} onOpenChange={setOpen}> <DialogContent> {/* content */} </DialogContent></Dialog>Alert Dialog
Confirmation dialog for destructive actions.
import { AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction } from '@kit/ui/alert-dialog';<AlertDialog> <AlertDialogTrigger asChild> <Button variant="destructive">Delete</Button> </AlertDialogTrigger> <AlertDialogContent> <AlertDialogHeader> <AlertDialogTitle>Are you sure?</AlertDialogTitle> <AlertDialogDescription> This action cannot be undone. </AlertDialogDescription> </AlertDialogHeader> <AlertDialogFooter> <AlertDialogCancel>Cancel</AlertDialogCancel> <AlertDialogAction>Delete</AlertDialogAction> </AlertDialogFooter> </AlertDialogContent></AlertDialog>Drawer
Slide-out panel from screen edge.
import { Drawer, DrawerTrigger, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerFooter, DrawerClose } from '@kit/ui/drawer';<Drawer> <DrawerTrigger asChild> <Button>Open Drawer</Button> </DrawerTrigger> <DrawerContent> <DrawerHeader> <DrawerTitle>Drawer Title</DrawerTitle> <DrawerDescription>Drawer description</DrawerDescription> </DrawerHeader> <div className="p-4"> Drawer content </div> <DrawerFooter> <Button>Submit</Button> <DrawerClose asChild> <Button variant="outline">Cancel</Button> </DrawerClose> </DrawerFooter> </DrawerContent></Drawer>Sheet
Side panel overlay (similar to drawer).
import { Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, SheetDescription } from '@kit/ui/sheet';<Sheet> <SheetTrigger asChild> <Button>Open Sheet</Button> </SheetTrigger> <SheetContent side="right"> <SheetHeader> <SheetTitle>Sheet Title</SheetTitle> <SheetDescription>Sheet description</SheetDescription> </SheetHeader> <div className="py-4"> Sheet content </div> </SheetContent></Sheet>Supports side prop: "top", "right", "bottom", "left".
Popover
Floating content anchored to trigger.
import { Popover, PopoverTrigger, PopoverContent } from '@kit/ui/popover';<Popover> <PopoverTrigger asChild> <Button variant="outline">Open Popover</Button> </PopoverTrigger> <PopoverContent> <div className="space-y-2"> <h4 className="font-medium">Popover Title</h4> <p className="text-sm text-muted-foreground"> Popover content goes here. </p> </div> </PopoverContent></Popover>Dropdown Menu
Menu triggered by button click.
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuLabel } from '@kit/ui/dropdown-menu';<DropdownMenu> <DropdownMenuTrigger asChild> <Button variant="outline"> Options <ChevronDown className="ml-2 h-4 w-4" /> </Button> </DropdownMenuTrigger> <DropdownMenuContent> <DropdownMenuLabel>Actions</DropdownMenuLabel> <DropdownMenuSeparator /> <DropdownMenuItem>Edit</DropdownMenuItem> <DropdownMenuItem>Duplicate</DropdownMenuItem> <DropdownMenuSeparator /> <DropdownMenuItem className="text-destructive"> Delete </DropdownMenuItem> </DropdownMenuContent></DropdownMenu>Context Menu
Right-click menu.
import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem } from '@kit/ui/context-menu';<ContextMenu> <ContextMenuTrigger className="flex h-32 w-full items-center justify-center rounded border border-dashed"> Right click here </ContextMenuTrigger> <ContextMenuContent> <ContextMenuItem>Copy</ContextMenuItem> <ContextMenuItem>Paste</ContextMenuItem> <ContextMenuItem>Delete</ContextMenuItem> </ContextMenuContent></ContextMenu>In MakerKit, we use Dialog for all settings forms and AlertDialog exclusively for delete confirmations. This consistency helps users build muscle memory - they know AlertDialog always means "this is destructive."
Common Pitfalls
- Dialog not closing after action: Controlled dialogs need
onOpenChangeto handle close state. CallsetOpen(false)in your action handler or useDialogClosewrapper. - Missing asChild on triggers: Triggers need
asChildprop when wrapping custom buttons:<DialogTrigger asChild><Button>Open</Button></DialogTrigger>. - Form submission closing dialog: Form onSubmit prevents dialog close by default. Use controlled state and close after successful submission.
- Popover z-index issues: Popovers inside other overlays may render behind. Use
style={{ zIndex: 100 }}on PopoverContent if needed. - AlertDialog vs Dialog confusion: Use AlertDialog only for destructive confirmations. For forms or complex content, use Dialog.
- Dropdown menu item not clickable: DropdownMenuItem needs an onClick handler or be wrapped with
asChildaround a Link/Button.
Frequently Asked Questions
When should I use Dialog vs AlertDialog?
How do I close a dialog programmatically?
What's the difference between Drawer and Sheet?
Why isn't my Popover appearing?
How do I prevent dialog close on backdrop click?
Next: Data Display →