modal

Display popup content that requires attention or provides additional information.

default

sticky

single button

disabled actions

inset

focus an input on open

mobile sheet with inputs

toasts and focus trap

best practices

When to use

  • Use Modal when a decision must block the rest of the page. For persistent associated context where the underlying page stays readable, use Sheet on desktop or Drawer on mobile.
  • Confirm destructive actions in a Modal. Drawer and Sheet don't fully dim the page, so they read as too soft for a delete or revoke.
  • Skip Modal for routine create flows that have a dedicated page; route to the page instead.

Behavior

  • Default focus to Cancel on any destructive Modal. Enter must never trigger the destructive action without a typed confirmation.
  • Allow Escape and outside-click to dismiss non-destructive modals; gate dismissal on destructive ones with unsaved input.
  • Trap focus inside the Modal while it's open and return focus to the trigger after close. Restore body scroll on the same tick the modal unmounts.
  • For high-stakes destructive actions, gate the primary button on a typed match of the resource name.

Content

  • Modal.Title is a Title Case statement, never a question. Transfer Project is correct; Transfer Project? is wrong.
  • Body copy is sentence case, one to three sentences. State the consequence first, then any cascade.
  • Primary button is Verb + Noun and matches the title verb. Never Confirm, OK, or a bare verb on a destructive primary.
  • The cancel literal stays Cancel. Acknowledgment-only modals use Done, never OK or Close.
  • Close irreversible bodies with This cannot be undone.; close cascade-only bodies with Some effects cannot be undone..
  • Pair the success toast verb one-to-one with the primary button: Delete Project button, Project deleted toast.

Accessibility

  • Set aria-labelledby to the Modal.Title id so screen readers announce the title on open.
  • Keep the cancel button literally Cancel so screen-reader users hear a stable dismissal label across destructive flows.
  • After an error inside the Modal, keep focus inside so the user can retry; after success, return focus to the trigger.