$npx -y skills add dembrandt/dembrandt-skills --skill modal-and-overlay-patternsOverlays — modals, drawers, bottom sheets, popovers — interrupt or augment the main flow. Each type has a different scope, blocking level, and appropriate use case. Use when designing dialogs, confirmation prompts, side panels, action sheets, or any UI element that appears above
| 1 | # Modal and Overlay Patterns |
| 2 | |
| 3 | Overlays appear above the main content layer. They range from lightweight popovers (non-blocking, anchored to a trigger) to full blocking modals (require a user response before the app continues). Choosing the right overlay type for the task prevents unnecessary interruption and keeps the user oriented. |
| 4 | |
| 5 | --- |
| 6 | |
| 7 | ## The Overlay Hierarchy |
| 8 | |
| 9 | Choose the lightest type that satisfies the task. Heavier overlays carry higher cognitive cost. |
| 10 | |
| 11 | | Type | Blocks background | Anchored to trigger | Typical content | Dismiss with | |
| 12 | |---|---|---|---|---| |
| 13 | | **Tooltip** | No | Yes | 1–2 lines of explanatory text | Cursor leave / focus out | |
| 14 | | **Popover** | No | Yes | Short interactive content: a form field, a picker, a small list | Click outside, Escape, explicit close | |
| 15 | | **Dropdown / Menu** | No | Yes | List of actions or options | Click outside, Escape, selection | |
| 16 | | **Bottom sheet** (mobile) | Partial (dimmed) | No | Actions or content on small screens | Swipe down, tap scrim, Escape | |
| 17 | | **Drawer / Side panel** | Partial (dimmed) | No | Secondary editing, detail views, long forms | Escape, explicit close; optionally click scrim | |
| 18 | | **Dialog / Modal** | Yes (full scrim) | No | Blocking task: confirm action, fill required form | Escape (non-destructive only), explicit button | |
| 19 | | **Full-screen overlay** | Yes (complete) | No | Immersive task: media viewer, complex configuration | Explicit close only | |
| 20 | |
| 21 | **Decision rule:** If the user can continue using the rest of the app while the overlay is open, use a non-blocking type (drawer, popover). If the app must wait for the user's response, use a modal. |
| 22 | |
| 23 | --- |
| 24 | |
| 25 | ## Tooltip |
| 26 | |
| 27 | A tooltip appears on hover or keyboard focus and disappears when the trigger loses focus. It is purely informational — no interactive elements inside. |
| 28 | |
| 29 | - Content: one short sentence, label, or keyboard shortcut. Never put a link or button inside a tooltip. |
| 30 | - Delay: 300–400ms on hover; no delay on keyboard focus. |
| 31 | - Position: prefer above the trigger; auto-flip when viewport edge is near. |
| 32 | - ARIA: `role="tooltip"` on the element; `aria-describedby` on the trigger pointing to the tooltip id. |
| 33 | |
| 34 | --- |
| 35 | |
| 36 | ## Popover |
| 37 | |
| 38 | A popover is anchored to a trigger but contains interactive content — a colour picker, a date range selector, a small form, a list of filters. Unlike a tooltip, it stays open while the user interacts. |
| 39 | |
| 40 | - Max width: 280–360px. For larger content, use a drawer. |
| 41 | - Position: anchored to the trigger; auto-flip to stay in viewport. |
| 42 | - Dismiss: click outside, Escape key, or explicit close button when the content is long. |
| 43 | - Focus: move focus into the popover when it opens; return focus to the trigger on close. |
| 44 | - ARIA: `role="dialog"` (if interactive) or `role="listbox"` (if a list); `aria-haspopup` on the trigger. |
| 45 | |
| 46 | --- |
| 47 | |
| 48 | ## Dropdown and Menu |
| 49 | |
| 50 | A dropdown lists selectable options or actions anchored to a trigger button. It is the lightest interactive overlay. |
| 51 | |
| 52 | - Separate **select dropdowns** (the user picks one value that persists) from **action menus** (the user triggers an action that doesn't persist as a value). |
| 53 | - Width: at least as wide as the trigger; cap at 280px. |
| 54 | - Long lists: add a search input at the top when there are more than 8–10 items. |
| 55 | - Keyboard: `↑`/`↓` to move between items, `Enter` to select, `Escape` to close. |
| 56 | |
| 57 | --- |
| 58 | |
| 59 | ## Bottom Sheet (Mobile) |
| 60 | |
| 61 | On small screens, a bottom sheet replaces modals and popovers. It slides up from the bottom edge and feels native to touch devices. |
| 62 | |
| 63 | - **Peek height:** Show a small portion of the sheet first (a handle + title), let the user drag to expand. |
| 64 | - **Full-height:** For longer content or forms that need the full vie |