Build Assets
UI Component

Modal / Dialog

Focused overlay for decisions, confirmations, or short forms that require immediate attention.

Platform: bothTags: modal, dialog, overlay, focus

Purpose

Interrupts the current flow to require a focused decision or acknowledgement. Use sparingly — only for actions that cannot safely proceed without explicit user intent.

Anatomy

  • Scrim: full-screen semi-transparent overlay (rgba 40% opacity)
  • Container: white card, centered, max-width 480–560px, 16px corner radius
  • Header: title (16–18px semibold) + optional close (×) button top-right
  • Body: content area, 24px padding, max-height with scroll for long content
  • Footer: action buttons right-aligned — primary action rightmost

States

  • Open: scrim visible, container centered with entrance animation
  • Closing: fade out scrim + slide down container (150ms)
  • Scroll: body scrolls independently when content exceeds max-height
  • Loading: primary action button shows loading state after submission

Tokens

spacing

padding: 24pxfooterGap: 8pxheaderBottomGap: 16px

sizing

maxWidth: 560pxminWidth: 320pxborderRadius: 16px

Do

  • Trap focus inside the modal while open (Tab cycles within)
  • Close on Escape key and scrim click (unless destructive action)
  • Keep to a single decision or task — no multi-step wizards in modals
  • Label the primary action with a verb ("Delete", "Save", "Confirm")

Don't

  • Open a modal from inside a modal (nested modals)
  • Use for informational content that doesn't require action
  • Use for multi-step flows — use a dedicated page instead
  • Use "OK" or "Yes" as button labels — use the action verb

Accessibility

  • role="dialog" with aria-modal="true" and aria-labelledby pointing to title
  • Focus moves to first focusable element on open
  • Focus returns to trigger element on close
  • Escape key closes the dialog
  • Scrim must not be focusable

Code Example

<div role="dialog" aria-modal="true" aria-labelledby="dialog-title">
  <h2 id="dialog-title">Delete item?</h2>
  <p>This action cannot be undone.</p>
  <div class="dialog-footer">
    <button type="button">Cancel</button>
    <button type="button" class="btn-danger">Delete</button>
  </div>
</div>

Source Topic

practical ui

Progressive Disclosure

Showing information and options at the moment they become relevant