Overlays
Layers above the page
Overlays interrupt. Use them only when the task needs focus or context the page can't give, and always make the way out obvious.
| Overlay | Use | Dismiss |
|---|---|---|
| Dialog (modal) | A decision that blocks: confirm destructive actions, unsaved changes, short focused forms | Buttons, Esc; scrim click only if nothing would be lost |
| Drawer | Detail or editing alongside a list: user details, filters, Mai docked panel | Close button, Esc, scrim |
| Bottom sheet | Mobile equivalent of drawers and menus | Swipe down, scrim, close button |
| Popover | Rich help or a small form anchored to a control | Outside click, Esc |
| Menu | A list of actions or options | Selection, outside click, Esc |
| Tooltip | Name or short hint for a control | Moving away, Esc |
Dialogs
Short, specific, safe
- Title asks the question or names the task: “Revoke licence for Noura Obaid?”
- Body says the consequence in one or two sentences.
- Buttons repeat the action (“Revoke licence”), not “OK”; the safe option is the secondary button; the destructive one is danger and last.
- Width 480px (640px for forms), 24px radius, shadow 4, on a Midnight scrim with 4px backdrop blur.
- Focus moves into the dialog, is trapped there, and returns to the trigger on close. Use the native
<dialog>element. - Never stack dialogs. Never open a dialog without a user action.
Drawers and bottom sheets
Context without leaving the page
- From the trailing edge (right; left in RTL), 380–480px wide, full height, shadow 4, with a scrim on narrow screens.
- Header with title and close button; footer with actions when editing.
- On mobile, drawers become bottom sheets with a handle and a maximum of 90% height.
- Mai's docked panel is a non-modal drawer: no scrim, the page stays usable.
Controls over images
Zoom, download, captions
- Overlay buttons sit in the top-right corner (top-left in RTL) with a 12px inset, in a row with 8px gaps: zoom first, then download, then more.
- They use the floating icon button: translucent Midnight 95 at 64%, Snow icon, 8px backdrop blur, 40px (32px in dense galleries).
- Visible on hover and keyboard focus on desktop; always visible on touch and when the image is the main content.
- Badges (status, “AI-generated”) go top-left. Captions go along the bottom on a Midnight gradient, Snow text 13px.
- Zoom opens a full-screen viewer on a 92% Midnight 95 backdrop with close (top right), arrows for galleries, pinch and Esc.
IllustrationHover or focus the image.
Controls over code and text
- Copy buttons on code blocks: top right inside the block header, always visible when there is a header; floating (top right, 10px inset, on hover/focus) when there isn't.
- Copy buttons on single values: an inline icon button right after the value.
- “Expand” on long code or text: a full-width “Show all 84 lines” button at the bottom of a faded block.
- Never cover the first line of content with a control: reserve the header row or the right gutter.
Placement rules
| Element | Anchored to | Offset | Collision |
|---|---|---|---|
| Menu, dropdown | Trigger, start-aligned below | 6px | Flip above; shift inside viewport |
| Popover | Trigger, centred below | 8px, with arrow | Flip to the side with most space |
| Tooltip | Element, centred above | 8px, with arrow | Flip below |
| Toast stack | Viewport bottom-right (bottom-left RTL; bottom-centre on mobile) | 24px | Stack upwards, max 3 |
| Image overlay buttons | Image top-right (top-left RTL) | 12px | — |
| Copy button | Code block top-right | 10px | — |
Code
<dialog class="n-dialog" aria-labelledby="t">
<h3 id="t">Revoke licence?</h3>
<p>…</p>
<div class="n-dialog__actions"><button class="n-btn n-btn--secondary">Cancel</button><button class="n-btn n-btn--danger">Revoke licence</button></div>
</dialog>
dialog::backdrop { background: var(--n-scrim); backdrop-filter: blur(var(--n-filter-blur-scrim)); }
<figure class="n-media"><img …><span class="n-media__actions"><button class="n-icon-btn n-icon-btn--float" aria-label="Zoom in">…</button></span></figure>Dos and don'ts
Do
- Use native dialog and return focus on close.
- Put overlay controls top right with a 12px inset.
- Name the action in the dialog button.
- Use bottom sheets on mobile.
Don't
- Open dialogs on page load.
- Stack overlays on overlays.
- Cover content with permanently visible controls.
- Use a dialog where an inline message would do.
Last updated on 14 October 2026