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.