|
| 1 | +# Getting started with overlays |
| 2 | + |
| 3 | +This guide helps you choose the right overlay approach for your use case and get up and running quickly. |
| 4 | + |
| 5 | +## Quick decision tree |
| 6 | + |
| 7 | +Choose your overlay entry point by answering these questions: |
| 8 | + |
| 9 | +### 1. What's your development approach? |
| 10 | + |
| 11 | +**Declarative HTML** → Continue to question 2 |
| 12 | + |
| 13 | +**Imperative JavaScript** → Continue to question 3 |
| 14 | + |
| 15 | +**Using Lit templates** → Use the [trigger directive](#trigger-directive-lit-only) |
| 16 | + |
| 17 | +### 2. Declarative HTML approach |
| 18 | + |
| 19 | +**Do you need multiple interaction types on the same trigger?** (e.g., click AND hover) |
| 20 | + |
| 21 | +- **Yes** → Use [`<overlay-trigger>`](#overlay-trigger) |
| 22 | +- **No** → Use [`<sp-overlay>`](#sp-overlay) |
| 23 | + |
| 24 | +### 3. Imperative JavaScript approach |
| 25 | + |
| 26 | +**Do you have a DOM element as the trigger?** |
| 27 | + |
| 28 | +- **Yes** → Use the [imperative API](#imperative-api) with a real element |
| 29 | +- **No** (positioning at cursor/coordinates) → Use the [imperative API](#imperative-api) with `VirtualTrigger` |
| 30 | + |
| 31 | +## Entry point comparison |
| 32 | + |
| 33 | +| Feature | `<sp-overlay>` | `<overlay-trigger>` | Imperative API | Trigger directive | |
| 34 | +| ------------------------- | -------------------------------- | ------------------------------------------ | ---------------------------------------- | ---------------------------------------------- | |
| 35 | +| **Development style** | Declarative HTML | Declarative HTML | Imperative JavaScript | Lit templates | |
| 36 | +| **Multiple interactions** | Single type per overlay | ✅ Click + hover + longpress | Single type per overlay | Single type per directive | |
| 37 | +| **Virtual positioning** | ✅ Via `triggerElement` property | ❌ Not supported | ✅ Via `VirtualTrigger` | ✅ Via options | |
| 38 | +| **Lazy content loading** | ✅ Via `slottable-request` | ✅ Automatic for each slot | ✅ Manual control | ✅ Automatic via directive | |
| 39 | +| **Best for** | Single interaction, fine control | Multiple interactions per trigger | Dynamic/programmatic use | Lit apps, reactive content | |
| 40 | +| **Setup complexity** | Simple | Simple | Moderate | Simple (with Lit) | |
| 41 | +| **Documentation** | [README.md](./README.md) | [overlay-trigger.md](./overlay-trigger.md) | [imperative-api.md](./imperative-api.md) | [trigger-directive.md](./trigger-directive.md) | |
| 42 | + |
| 43 | +## Common use cases |
| 44 | + |
| 45 | +Jump directly to patterns for common scenarios: |
| 46 | + |
| 47 | +### Tooltips |
| 48 | + |
| 49 | +**Simple hover tooltip** → Use `<sp-overlay>` with `trigger="element@hover"` and `type="hint"` |
| 50 | + |
| 51 | +```html |
| 52 | +<sp-button id="help-button">Help</sp-button> |
| 53 | +<sp-overlay trigger="help-button@hover" type="hint" placement="top"> |
| 54 | + <sp-tooltip>Click for more information</sp-tooltip> |
| 55 | +</sp-overlay> |
| 56 | +``` |
| 57 | + |
| 58 | +**Tooltip with click action** → Use `<overlay-trigger>` with both hover and click content |
| 59 | + |
| 60 | +```html |
| 61 | +<overlay-trigger placement="top"> |
| 62 | + <sp-button slot="trigger">Help</sp-button> |
| 63 | + <sp-tooltip slot="hover-content">Click for more info</sp-tooltip> |
| 64 | + <sp-popover slot="click-content"> |
| 65 | + <sp-dialog size="s"> |
| 66 | + <h2 slot="heading">Help</h2> |
| 67 | + <p>Detailed help information here...</p> |
| 68 | + </sp-dialog> |
| 69 | + </sp-popover> |
| 70 | +</overlay-trigger> |
| 71 | +``` |
| 72 | + |
| 73 | +### Modal dialogs |
| 74 | + |
| 75 | +**Confirmation dialog** → Use `<sp-overlay>` with `type="modal"` |
| 76 | + |
| 77 | +```html |
| 78 | +<sp-button id="delete-button">Delete</sp-button> |
| 79 | +<sp-overlay trigger="delete-button@click" type="modal"> |
| 80 | + <sp-dialog-wrapper headline="Confirm deletion" dismissable underlay> |
| 81 | + <p>Are you sure you want to delete this item?</p> |
| 82 | + <sp-button slot="button" variant="accent">Delete</sp-button> |
| 83 | + <sp-button |
| 84 | + slot="button" |
| 85 | + onclick="this.dispatchEvent(new Event('close', {bubbles: true}))" |
| 86 | + > |
| 87 | + Cancel |
| 88 | + </sp-button> |
| 89 | + </sp-dialog-wrapper> |
| 90 | +</sp-overlay> |
| 91 | +``` |
| 92 | + |
| 93 | +### Context menus |
| 94 | + |
| 95 | +**Right-click menu** → Use imperative API with `VirtualTrigger` |
| 96 | + |
| 97 | +```javascript |
| 98 | +import { VirtualTrigger, openOverlay } from '@spectrum-web-components/overlay'; |
| 99 | + |
| 100 | +element.addEventListener('contextmenu', async (event) => { |
| 101 | + event.preventDefault(); |
| 102 | + |
| 103 | + const virtualTrigger = new VirtualTrigger(event.clientX, event.clientY); |
| 104 | + const menu = document.createElement('sp-popover'); |
| 105 | + menu.innerHTML = ` |
| 106 | + <sp-menu> |
| 107 | + <sp-menu-item>Cut</sp-menu-item> |
| 108 | + <sp-menu-item>Copy</sp-menu-item> |
| 109 | + <sp-menu-item>Paste</sp-menu-item> |
| 110 | + </sp-menu> |
| 111 | + `; |
| 112 | + |
| 113 | + const overlay = await openOverlay(menu, { |
| 114 | + trigger: virtualTrigger, |
| 115 | + placement: 'right-start', |
| 116 | + type: 'auto', |
| 117 | + }); |
| 118 | + |
| 119 | + element.appendChild(overlay); |
| 120 | +}); |
| 121 | +``` |
| 122 | + |
| 123 | +### Dropdown pickers |
| 124 | + |
| 125 | +**Select menu** → Use `<sp-overlay>` with `type="auto"` |
| 126 | + |
| 127 | +```html |
| 128 | +<sp-button id="picker-trigger">Choose option</sp-button> |
| 129 | +<sp-overlay trigger="picker-trigger@click" type="auto" placement="bottom-start"> |
| 130 | + <sp-popover> |
| 131 | + <sp-menu> |
| 132 | + <sp-menu-item>Option 1</sp-menu-item> |
| 133 | + <sp-menu-item>Option 2</sp-menu-item> |
| 134 | + <sp-menu-item>Option 3</sp-menu-item> |
| 135 | + </sp-menu> |
| 136 | + </sp-popover> |
| 137 | +</sp-overlay> |
| 138 | +``` |
| 139 | + |
| 140 | +## Entry point details |
| 141 | + |
| 142 | +### `<sp-overlay>` |
| 143 | + |
| 144 | +**When to use:** |
| 145 | + |
| 146 | +- Single interaction type per trigger (click, hover, or longpress) |
| 147 | +- Need fine-grained control over overlay behavior |
| 148 | +- Working with virtual triggers or dynamic positioning |
| 149 | + |
| 150 | +**Pros:** |
| 151 | + |
| 152 | +- Most flexible and feature-complete |
| 153 | +- Supports all overlay types and configurations |
| 154 | +- Works with `VirtualTrigger` for cursor-based positioning |
| 155 | + |
| 156 | +**Cons:** |
| 157 | + |
| 158 | +- Need separate overlays for multiple interaction types |
| 159 | +- Slightly more verbose than `<overlay-trigger>` |
| 160 | + |
| 161 | +**Learn more:** [README.md](./README.md) |
| 162 | + |
| 163 | +### `<overlay-trigger>` |
| 164 | + |
| 165 | +**When to use:** |
| 166 | + |
| 167 | +- Need multiple interactions on the same trigger (e.g., hover tooltip + click dialog) |
| 168 | +- Want automatic content management per interaction type |
| 169 | +- Prefer slot-based API |
| 170 | + |
| 171 | +**Pros:** |
| 172 | + |
| 173 | +- Handles multiple interaction types elegantly |
| 174 | +- Automatic content lifecycle management |
| 175 | +- Clean slot-based API |
| 176 | + |
| 177 | +**Cons:** |
| 178 | + |
| 179 | +- Cannot use `VirtualTrigger` (requires real DOM element) |
| 180 | +- Less control over individual overlay behaviors |
| 181 | +- Hover content is always `hint` type (non-interactive) |
| 182 | + |
| 183 | +**Learn more:** [overlay-trigger.md](./overlay-trigger.md) |
| 184 | + |
| 185 | +### Imperative API |
| 186 | + |
| 187 | +**When to use:** |
| 188 | + |
| 189 | +- Building components that need programmatic overlay control |
| 190 | +- Dynamic overlay creation based on runtime conditions |
| 191 | +- Context menus or cursor-following overlays |
| 192 | +- Complex lifecycle management requirements |
| 193 | + |
| 194 | +**Pros:** |
| 195 | + |
| 196 | +- Full programmatic control |
| 197 | +- Works with `VirtualTrigger` for any position |
| 198 | +- Can create overlays on-demand |
| 199 | +- Easy cleanup and disposal |
| 200 | + |
| 201 | +**Cons:** |
| 202 | + |
| 203 | +- More code to write |
| 204 | +- Manual DOM management |
| 205 | +- Need to handle async operations |
| 206 | + |
| 207 | +**Learn more:** [imperative-api.md](./imperative-api.md) |
| 208 | + |
| 209 | +### Trigger directive (Lit only) |
| 210 | + |
| 211 | +**When to use:** |
| 212 | + |
| 213 | +- Working in Lit-based applications |
| 214 | +- Need reactive overlay content |
| 215 | +- Want template composition benefits |
| 216 | +- Building reusable Lit components |
| 217 | + |
| 218 | +**Pros:** |
| 219 | + |
| 220 | +- Integrates seamlessly with Lit |
| 221 | +- Automatic reactive updates |
| 222 | +- Lazy content rendering |
| 223 | +- Clean template syntax |
| 224 | + |
| 225 | +**Cons:** |
| 226 | + |
| 227 | +- Only works with Lit |
| 228 | +- Single interaction type per directive |
| 229 | +- Need to understand Lit directives |
| 230 | + |
| 231 | +**Learn more:** [trigger-directive.md](./trigger-directive.md) |
| 232 | + |
| 233 | +## Next steps |
| 234 | + |
| 235 | +1. **Choose your entry point** using the decision tree above |
| 236 | +2. **Read the detailed documentation** for your chosen approach |
| 237 | +3. **Explore [Storybook examples](../../storybook/)** to see patterns in action |
| 238 | +4. **Review [common patterns](./README.md#integration-patterns)** for your use case |
| 239 | +5. **Check [troubleshooting guide](./TROUBLESHOOTING.md)** if you encounter issues |
| 240 | + |
| 241 | +## Additional resources |
| 242 | + |
| 243 | +- [Architecture documentation](./ARCHITECTURE.md) - Deep dive into how the overlay system works |
| 244 | +- [Accessibility guide](./ACCESSIBILITY.md) - Focus management and ARIA patterns |
| 245 | +- [Performance guide](./PERFORMANCE.md) - Optimization strategies |
| 246 | +- [Forms integration](./FORMS-INTEGRATION.md) - Validation popovers and field helpers |
| 247 | +- [Menus integration](./MENUS-INTEGRATION.md) - Action menus and dropdown patterns |
0 commit comments