Modal
Display popup content that requires attention or provides additional information.
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
Cancelon 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 (delete production resource, rotate signing key, downgrade plan), gate the primary button on a typed match of the resource name.
Content
Modal.Titleis a Title Case statement, never a question.Transfer Projectis correct;Transfer Project?is wrong.Modal.Pbody is sentence case, 1–3 sentences. State the consequence first, then any cascade.- Primary button is
Verb + Nounand matches the title verb (Transfer Projecttitle pairs withTransfer Projectbutton). NeverConfirm,OK, or a bare verb on a destructive primary. - Cancel literal stays
Cancel. Acknowledgment-only Modals (after a key reveal, after a one-time-show) useDone, neverOKorClose. - Close irreversible bodies with
This cannot be undone.; close cascade-only bodies withSome effects cannot be undone.. Don’t claim full irreversibility for a partial cascade. - Pair the success toast verb 1:1 with the primary button:
Delete Projectbutton,Project deletedtoast.
Accessibility
- Set
aria-labelledbyto theModal.Titleid so screen readers announce the title on open. - Keep the Cancel button literally
Cancelso 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.
Was this helpful?