Dialogs
Generated from DESIGN_SYSTEM.md
Rules
A dialog interrupts, so it is the last resort, not the default container. It is right for three things only: confirming an action that cannot be undone, a short focused task the person must finish or cancel (creating a hub), and a decision the app cannot proceed without (a new version is ready). Settings, filters and anything adjusted while looking at the content open inline, in a popover or in a side panel with a live preview — never a modal.
- Undo before confirm. A destructive action that can be reversed (a soft delete) runs at once and offers Undo for 30 seconds. A confirm dialog is reserved for what cannot be taken back: a payment, a permanent deletion, a message sent to other people.
- Say what happens. The title names the action ("Delete this hub?"); the body is one or two sentences on what will happen and what cannot be recovered. No "Are you sure?" with nothing else.
- The confirm button carries the verb ("Delete hub", "Send"), never "OK" or "Confirm". A destructive confirm is
btn-danger; cancel is a quiet button beside it. - Button order: from
smup the actions sit right-aligned with the primary last; on phones they stack full width with the primary on top, next to the thumb.
| Phones | From sm up | |
|---|---|---|
| Shape | Bottom sheet: full width, rounded top corners | Centered, max-w-md (wide content up to max-w-xl) |
| Layer | Dimmed backdrop z-overlay, panel z-modal | Same |
| Elevation | The modal elevation token | Same |
Behavior — every dialog, every platform:
- It is announced as a dialog and labelled by its title (
role="dialog",aria-modal,aria-labelledbyon the web). - Focus moves into the dialog when it opens and stays inside it while it is open.
- Escape closes it, as Cancel does; so does a tap on the backdrop, except while a submit is in flight.
- Focus returns to the control that opened it when it closes.
- The page behind does not scroll.
| Platform | Confirm | Task or sheet |
|---|---|---|
| Web | ConfirmModal from @yroun/ui | ModalView from @yroun/ui |
| iOS | .confirmationDialog or .alert with role: .destructive | .sheet with presentationDetents and a visible drag indicator |
| Android | Material 3 AlertDialog | ModalBottomSheet |
The browser's window.confirm is never used: it cannot be styled, translated or tested, and it blocks the page.