Learning Track
Filter content by your role to see the most relevant sections
Dialogs & Overlay Patterns
Master the overlay family: dialogs that trap and return focus, sheets and popovers sized to intent, tooltips that respect delay and dismissal, entrance/exit motion from the interaction composites, and the elevation semantics that keep layering honest.
Why This Matters
Overlays are the interface raising its voice. Done well, a dialog is a focused conversation—attention narrows, a decision happens, context resumes untouched. Done badly, it is an ambush: focus lost, background scrolling, the close button a mystery, the keyboard user stranded outside looking in. The difference is never visual polish; it is whether the overlay honors four contracts simultaneously—focus, dismissal, layering, and motion.
This system treats the whole family—Dialog, Sheet, Popover, Tooltip, Walkthrough—as one pattern with a shared contract, declared in each component's contract file and expressed through the foundations you have already met: elevation for layering, motion composites for entrance and exit, and the accessibility tree for everything that matters most.
Core Concepts: The Four Contracts
Contract 1: Focus Is Borrowed, Then Returned
An open overlay owns focus: it moves focus into itself on open, cycles Tab within itself while open (the trap), and—most forgotten—returns focus to the trigger on close. The Dialog contract declares exactly this:
// ui/components/Dialog/Dialog.contract.json (excerpt)
"role": "dialog",
"labeling": ["aria-label"],
"keyboard": [{ "key": "Enter|Space", /* trigger semantics */ },
/* + Tab cycling, Escape to close */]
// The pattern's invariants:
// open → focus moves to the dialog (title or first control)
// open → Tab cycles inside; background is inert
// close → focus returns to the invoking triggerThe return is the invariant teams drop, and it is the one that strands keyboard users at the page start—their context destroyed by a closed dialog they successfully used.
Contract 2: Dismissal Is Obvious and Redundant
- Escape closes—every overlay, no exceptions; it is the user's universal exit.
- A visible close affordance—icon button with a real name ("Close"), the Icon binary's meaningful case.
- Scrim click closes—except for destructive or flow dialogs, where an accidental click losing a form is worse than rigidity. The rule is declared per usage, and the destructive case says why it is exempt.
Contract 3: Layering Is Semantic, Not Decorative
Overlays sit at the top of the elevation story: the scrim is flat with the page, the dialog panel is surface.floating (level 2) or the modal step for the heavyweight cases, and the stacking order (elevation.depth) must agree with the shadow—a tooltip that renders above a modal in z-index but below it visually is a lie in one channel or the other. Nested overlays compose deliberately: popover over dialog over page, each layer's depth greater than its parent's.
Contract 4: Motion With an Exit Faster Than the Entrance
The composites encode the family's timing: modal enters on medium2 + soft.enter (333ms, comfortable arrival) and exits on medium1 + soft.exit (250ms)—arriving information is worth perceiving; departing information is not. Tooltips invert the ratio with a delay.medium (100ms) entry so grazing does not spam, and a short1 (50ms) exit so they vanish without ceremony. And the whole family carries its prefers-reduced-motion block: fades survive, travel does not.
Choosing the Family Member
Dialog — interruptive, modal: the user must decide
Sheet — the dialog's side-dwelling cousin (tasks, filters)
Popover — anchored, transient, non-modal by default
Tooltip — deferential: explains, never acts; no focus of its own
Walkthrough — sequenced guidance riding the same machinery
The chooser is attention budget, not aesthetics: how much of the
user's context does this surface need to take?System Roles: Owning the Contracts
Design Impact
Designers own the attention decision—which family member, how modal, what the scrim obscures—and the destructive-dialog exemptions, argued per case.
Engineering Impact
Engineers own the invariants: trap, return, inert background, Escape, depth-order agreement. The contract file is where each is declared; the e2e walk is where each is proven.
Accessibility Impact
The a11y function owns the announcement quality: dialog names (aria-label carrying the title), the scrim's silence, and the manual pass on focus return.
Design & Code Interplay
The design side of overlays is the layer diagram: page, scrim, panel, nested layers—with the elevation role and the motion timing annotated per layer. The comp answers "how much context does this take?" visually (scrim opacity, panel offset) before code answers it structurally.
The contracts, as one dialog's implementation:
function Dialog({ open, onClose, title, trigger }) {
// Focus: in on open, cycled while open, returned on close
// Inert: background unreachable (aria-hidden + pointer-events)
// Layer: scrim flat, panel floating, depth ordered
// Motion: enter medium2/soft.enter, exit medium1/soft.exit
return (
<Overlay show={open} onEscape={onClose}>
<div role="dialog" aria-label={title}
data-ds-component="Dialog"> {/* contract-bound */}
{children}
</div>
</Overlay>
);
}
// The e2e walk that proves the invariants:
// tab to trigger → Enter → focus inside dialog
// Tab × n → focus never escapes the panel
// Escape → dialog closes → focus is BACK on the triggerApplied Example: A Destructive Confirm Dialog
The hardest overlay used well—"Delete this project?":
- Family choice: interruption is the point → Dialog, modal, with a titled scrim.
- Wording: the title names the object; the body names the consequence; the buttons are "Delete project" / "Cancel" (the affirmative says what it does—no generic OK).
- Destructive styling: the affirmative action uses the destructive ramp, focus lands on Cancel (safe default first), and the scrim click is exempt—accidentally deleting is worse than one extra click.
- Contracts: Escape cancels; focus returns to the row's menu trigger; depth above any popover that opened the flow; motion on the composites with reduced-motion fades.
- Verify: the keyboard walk including focus return, axe on the open state, and one VoiceOver pass confirming the announced title.
Constraints & Trade-offs
- Modality vs context: modality focuses decisions and blocks all else—the strongest tool and the most abused. The system bias: non-modal by default, modal by declared necessity.
- Scrim dismissability vs safety: click-to-dismiss speeds casual flows and destroys careful ones; destructive dialogs opt out, loudly.
- One overlay vs stacked overlays: stacks multiply every invariant; most stacks are a navigation design failure wearing a component solution.
Common Pitfalls & Failure Modes
1. The vanishing focus
Dialog closes, focus snaps to body. The return invariant exists precisely for this; it is contract behavior, not a nicety.
2. The leaky trap
Tab escapes to browser chrome or hidden background controls—background inertness is part of the same contract, not a separate feature.
3. Tooltip as control
Tooltips explain; they never hold actions—keyboard and touch users cannot reach them. Interactive content belongs in a popover with focus.
4. Depth disagreement
/* Bad: Level-3 shadow under a level-1 bar */
.modal { z-index: 10; box-shadow: var(--core-elevation-level-3); }
.nav { z-index: 100; }
/* Good: Depth numbers order with shadow levels */5. Motion without exit
Entrances animated, closes instant—the overlay family lives or exits together; the composites price both.
Verification Checklist
Additional Resources
- Elevation & Shadows — the layering semantics overlays ride (
/blueprints/foundations/elevation) - Motion & Duration — the composites that time the family (
/blueprints/foundations/motion) - ARIA APG dialog pattern — the reference behavior (
https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/)
Related Concepts
Reflection Questions
Apply This Concept
Take a stacked-overlay flow you know (popover → dialog → dialog?) and rewrite it as a single dialog or a page. What invariants did the stack multiply, and what did the redesign eliminate?
Reflect
A product spec asks for tooltips containing a link. Which contract does that violate, which family member belongs there instead, and what changes for touch users?
