Skip to main content

Dialog

Modal dialogs with focus trapping and accessible announcements.

Usage

<w-dialog label="Confirm Action">
<w-slot trigger><button>Open Dialog</button></w-slot>
<w-slot body>
<div>
<h2>Are you sure?</h2>
<p>This action cannot be undone.</p>
<w-slot close><button>Cancel</button></w-slot>
<button>Confirm</button>
</div>
</w-slot>
</w-dialog>

Props

PropTypeDefaultDescription
openbooleanfalseWhether the dialog is open
modalbooleantrueTrap focus and add backdrop
persistentbooleanfalsePrevent closing via Escape or outside click
closeOnEscapebooleantrueClose when Escape is pressed
closeOnOutsideClickbooleantrueClose when clicking outside
returnFocusbooleantrueReturn focus to trigger on close
labelstring""Accessible label for the dialog

Slots

SlotElementDescription
triggerButtonElement that opens the dialog
contentAnyDialog content (teleported to portal)
closeButtonClose button inside content

Events

EventDescription
openFired when dialog opens
closeFired when dialog closes

Methods

MethodDescription
showModal()Open the dialog
close()Close the dialog
toggle(force?)Toggle open state, optionally force a state

Keyboard

KeyAction
Enter / SpaceOpen dialog (on trigger)
EscapeClose dialog
TabCycle through focusable elements (trapped)

CSS Transitions

The dialog supports CSS transitions using these classes:

/* Enter transition */
.dialog-enter { }
.dialog-enter-from { opacity: 0; transform: scale(0.95); }
.dialog-enter-to { opacity: 1; transform: scale(1); }

/* Leave transition */
.dialog-leave { }
.dialog-leave-from { opacity: 1; }
.dialog-leave-to { opacity: 0; }

Examples

Non-Modal Dialog

<w-dialog modal="false" label="Side Panel">
<w-slot trigger><button>Open Panel</button></w-slot>
<w-slot body>
<div>
<!-- No focus trap, no backdrop -->
</div>
</w-slot>
</w-dialog>

Programmatic Control

<w-dialog id="my-dialog" label="Alert">
<w-slot body>
<div>
<p>Something happened!</p>
<w-slot close><button>OK</button></w-slot>
</div>
</w-slot>
</w-dialog>

<script>
const dialog = document.getElementById('my-dialog');
dialog.showModal(); // Open
dialog.close(); // Close
</script>

Persistent Dialog

A persistent dialog cannot be dismissed by pressing Escape or clicking outside. The user must explicitly close it via the close button or programmatically.

<w-dialog persistent label="Important Action Required">
<w-slot trigger><button>Open Persistent Dialog</button></w-slot>
<w-slot body>
<div>
<h2>Action Required</h2>
<p>You must complete this action before continuing.</p>
<w-slot close><button>I understand</button></w-slot>
</div>
</w-slot>
</w-dialog>

Accessibility

  • role="dialog" on content
  • aria-modal="true" when modal
  • aria-label from label prop
  • Focus trapped within modal
  • Focus returned to trigger on close
  • Escape key closes dialog