Dialog
Focus-trapped modal with accessible overlay and content.
Dialog
Dialog is a focus-trapped modal component. It renders content in a portal (separate from the DOM tree), manages focus cycling, and can be dismissed via Escape or outside click (optional). Unlike AlertDialog, users can dismiss Dialog without explicit action.
Usage
import { Dialog, DialogTrigger, DialogContent, DialogTitle, DialogDescription, DialogClose } from '@loke/ui/dialog';
export default function Example() {
return (
<Dialog>
<DialogTrigger asChild>
<button>Open dialog</button>
</DialogTrigger>
<DialogContent>
<DialogTitle>Dialog Title</DialogTitle>
<DialogDescription>
Dialog description goes here.
</DialogDescription>
<DialogClose asChild>
<button>Close</button>
</DialogClose>
</DialogContent>
</Dialog>
);
}Sub-components
- DialogTrigger — Button or element that opens the dialog
- DialogPortal — Renders dialog in a portal (typically to document.body)
- DialogOverlay — Backdrop overlay (semi-transparent)
- DialogContent — Dialog container with focus trapping
- DialogTitle — Accessible title
- DialogDescription — Description text
- DialogClose — Close button
Props
Prop
Type
Examples
Basic dialog
Controlled dialog
Status: closed
Accessibility
- Focus is trapped within the dialog; Tab cycles through focusable elements.
- Escape key closes the dialog.
- Outside clicks close the dialog (configurable).
- Dialog has role="dialog" and aria-labelledby pointing to the title.
- Body scroll is prevented while dialog is open.
- Focus returns to the trigger when closed.
Best practices
- Always include a DialogTitle for accessibility.
- Provide a clear DialogDescription explaining the dialog's purpose.
- Include a close button or make Escape obvious.
- Use DialogPortal to render in document.body for proper stacking.
- For critical confirmations, use AlertDialog instead.