Skip to content

Commit 2311a0e

Browse files
committed
docs(overlay): a11y docs update
1 parent f79cd52 commit 2311a0e

File tree

7 files changed

+526
-319
lines changed

7 files changed

+526
-319
lines changed

packages/overlay/README.md

+279-177
Large diffs are not rendered by default.

packages/overlay/imperative-api.md

+23-25
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## Description
1+
## Overview
22

33
While an `<sp-overlay>` element is the recommended entry point to the Spectrum Web Components Overlay API, you can also interact with this set of features via an imperative API, `Overlay.open`.
44

@@ -7,19 +7,21 @@ While an `<sp-overlay>` element is the recommended entry point to the Spectrum W
77
[![See it on NPM!](https://img.shields.io/npm/v/@spectrum-web-components/overlay?style=for-the-badge)](https://www.npmjs.com/package/@spectrum-web-components/overlay)
88
[![How big is this package in your project?](https://img.shields.io/bundlephobia/minzip/@spectrum-web-components/overlay?style=for-the-badge)](https://bundlephobia.com/result?p=@spectrum-web-components/overlay)
99

10-
```
10+
```zsh
1111
yarn add @spectrum-web-components/overlay
1212
```
1313

1414
Import the `Overlay` class to leverage its capabilities within your application or custom element:
1515

16-
```js
16+
```ts
1717
import { Overlay } from '@spectrum-web-components/overlay';
1818
```
1919

20+
### Example
21+
2022
Primarily, this class gives you access to the `open` method that will allow you to open an overlay:
2123

22-
```js
24+
```ts
2325
Overlay.open(
2426
(overlayElement: HTMLElement), // the element that will be projected into the overlay, "content",
2527
(options?: OverlayOptions)
@@ -28,7 +30,7 @@ Overlay.open(
2830

2931
`Overlay.open()` is an asynchronous method that returns an `<sp-overlay>` element that wraps the `HTMLElement` provided as the `overlayElement`. While this process will set the `<sp-overlay>` element to `open`, consumers of this API will need to choose where to append this element to the DOM in order for the content to be made available in the browser.
3032

31-
```js
33+
```ts
3234
(async () => {
3335
const content = document.querySelector('#content');
3436
const options = {
@@ -44,7 +46,7 @@ Overlay.open(
4446

4547
Keep in mind that a changing DOM tree is likely to alter the relationship between existing content. Without proper care this can negatively effect the CSS that you have applied to existing content. DOM events and DOM selection methods can also perform differently than expected as the tree shape changes.
4648

47-
## OverlayOptions
49+
### Options
4850

4951
When leveraging `Overlay.open()`, you can provide an optional second argument of `OverlayOptions`, with the following type:
5052

@@ -60,33 +62,39 @@ type OverlayOptions = {
6062
};
6163
```
6264

63-
### delayed
65+
#### `delayed`
6466

6567
An Overlay that is `delayed` will wait until a warm-up period of 1000ms has completed before opening. Once the warmup period has completed, all subsequent Overlays will open immediately. When no Overlays are opened, a cooldown period of 1000ms will begin. Once the cooldown has completed, the next Overlay to be opened will be subject to the warm-up period if provided that option.
6668

67-
### notImmediatelyCloseable
69+
#### `notImmediatelyCloseable`
6870

6971
When an Overlay is `notImmediatelyCloseable` that means that the first interaction that would lead to the closure of the Overlay in question will be ignored. This is useful when working with non-"click" mouse interactions, like `contextmenu`, where the trigger event (e.g. `contextmenu`) occurs _before_ an event that would close said overlay (e.g. `pointerup`).
7072

71-
### offset
73+
#### `offset`
7274

7375
The `offset` property accepts either a single number, to define the offset of the Overlay along the main axis from the trigger, or 2-tuple, to define the offset along the main axis and the cross axis. This option has no effect when there is no trigger element.
7476

75-
### placement
77+
#### `placement`
7678

7779
A `placement` of `"auto-start" | "auto-end" | "top" | "bottom" | "right" | "left" | "top-start" | "top-end" | "bottom-start" | "bottom-end" | "right-start" | "right-end" | "left-start" | "left-end"` will instruct the Overlay where to place itself in relationship to the trigger element.
7880

79-
### receivesFocus
81+
#### `receivesFocus`
8082

8183
Some Overlays will always be passed focus (e.g. modal or page Overlays). When this is not true, the `receivesFocus` option will inform the API whether to attempt to pass focus into the Overlay once it is open. `'true'` will pass focus, `'false'` will not (when possible), and `"auto"` (the default), will make a decision based on the `type` of the Overlay.
8284

83-
### trigger
85+
#### `trigger`
8486

8587
The `trigger` option accepts an `HTMLElement` or a `VirtualTrigger` from which to position the Overlay.
8688

8789
- You can import the `VirtualTrigger` class from the overlay package to create a virtual trigger that can be used to position an Overlay. This is useful when you want to position an Overlay relative to a point on the screen that is not an element in the DOM, like the mouse cursor.
8890

89-
### Using a virtual trigger
91+
#### `type`
92+
93+
The `type` of an Overlay outlines a number of things about the interaction model within which it works which are described in the [Overlay types](https://opensource.adobe.com/spectrum-web-components/components/overlay/#overlay-types).
94+
95+
### Advanced topics
96+
97+
#### Using a virtual trigger
9098

9199
```html-live
92100
<style>
@@ -163,11 +171,11 @@ The `trigger` option accepts an `HTMLElement` or a `VirtualTrigger` from which t
163171

164172
<script type="module">
165173

166-
import { html, render } from '@spectrum-web-components/base';
174+
import { html, render } from '@spectrum-web-components/base';
167175
import { VirtualTrigger, openOverlay } from '@spectrum-web-components/overlay';
168176

169177
const contextMenuTemplate = () => html`
170-
<sp-popover
178+
<sp-popover
171179
style="width:300px;"
172180
@change=${(event) => {
173181
event.target.dispatchEvent(
@@ -218,13 +226,3 @@ The `trigger` option accepts an `HTMLElement` or a `VirtualTrigger` from which t
218226
});
219227
});
220228
</script>
221-
222-
### type
223-
224-
The `type` of an Overlay outlines a number of things about the interaction model within which is works.
225-
226-
- `'modal'` Overlays create a modal context that traps focus within the content and prevents interaction with the rest of the page. The overlay manages focus trapping and accessibility features like `aria-modal="true"` to ensure proper screen reader behavior.
227-
- `'page'` Overlays behave similarly to `'modal'` Overlays by creating a modal context and trapping focus, but they will not be allowed to close via the "light dismiss" algorithm (e.g. the Escape key).
228-
- `'hint'` Overlays are much like tooltips so they are not just ephemeral, but they are delivered primarily as a visual helper and exist outside of the tab order. In this way, be sure _not_ to place interactive content within this type of Overlay.
229-
- `'auto'` Overlays provide a place for content that is ephemeral _and_ interactive. These Overlays can accept focus but will close when losing that focus, or when interacting with other parts of the page.
230-
- `'manual'` Overlays act much like `"auto"` Overlays, but do not close when losing focus or interacting with other parts of the page. When a `"manual"` Overlay is at the top of the "overlay stack", it will still respond to the Escape key and close.

packages/overlay/overlay-trigger.md

+89-63
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
</div>
1818
</div>
1919

20-
## Description
20+
## Overview
2121

2222
An `<overlay-trigger>` element supports the delivery of temporary overlay content based on interaction with a persistent trigger element. An element prepared to receive accessible interactions (e.g. an `<sp-button>`, or `<button>`, etc.) is addressed to `slot="trigger"`, and the content to display (either via `click` or `hover`/`focus` interactions) is addressed to `slot="click-content"` or `slot="hover-content"`, respectively. A trigger element can be linked to the delivery of content, intended for a single interaction, or both. Content addressed to `slot="hover-content"` is made available when the mouse enters or leaves the target element. Keyboard navigation will make this content available when focus enters or leaves the target element. Be thoughtful with what content you address to `slot="hover-content"`, as the content available via "hover" will be transient and non-interactive.
2323

@@ -27,79 +27,31 @@ An `<overlay-trigger>` element supports the delivery of temporary overlay conten
2727
[![How big is this package in your project?](https://img.shields.io/bundlephobia/minzip/@spectrum-web-components/meter?style=for-the-badge)](https://bundlephobia.com/result?p=@spectrum-web-components/overlay)
2828
[![Try it on webcomponents.dev](https://img.shields.io/badge/Try%20it%20on-webcomponents.dev-green?style=for-the-badge)](https://webcomponents.dev/edit/collection/fO75441E1Q5ZlI0e9pgq/bu0sOBIfyW7wnHkXtGzL/src/index.ts)
2929

30-
```
30+
```zsh
3131
yarn add @spectrum-web-components/overlay
3232
```
3333

3434
Import the side-effectful registration of `<overlay-trigger>` via:
3535

36-
```
36+
```ts
3737
import '@spectrum-web-components/overlay/overlay-trigger.js';
3838
```
3939

4040
The default of `<overlay-trigger>` will load dependencies in `@spectrum-web-components/overlay` asynchronously via a dynamic import. In the case that you would like to import those tranverse dependencies statically, import the side effectful registration of `<overlay-trigger>` as follows:
4141

42-
```
42+
```ts
4343
import '@spectrum-web-components/overlay/sync/overlay-trigger.js';
4444
```
4545

4646
When looking to leverage the `OverlayTrigger` base class as a type and/or for extension purposes, do so via:
4747

48-
```
48+
```ts
4949
import { OverlayTrigger } from '@spectrum-web-components/overlay';
5050
```
5151

52-
### Placement
53-
54-
When using the `placement` attribute of an `<overlay-trigger>` (`"top" |"top-start" | "top-end" | "bottom" | "bottom-start" | "bottom-end" | "right" | "right-start" | "right-end" | "left" | "left-start" | "left-end"`), you can suggest to the overlay in which direction relative to the trigger that the content should display. When there is adequate room for the content to display in the specified direction, it will do so. When adequate room is not available, the overlaid content will calculate the direction in which it has the most room to be displayed and use that direction.
55-
56-
### Type
52+
### Example
5753

58-
The `type` attribute of an `<overlay-trigger>` element outlines how the element's "click" content should appear in the tab order. `inline` will insert the overlay after the trigger; from here, forward tabbing targets the next logical element, and backward/shift tabbing returns to the target. `replace` will insert the overlay into the page as if it were the trigger; from here, forward tabbing targets the next logical element, and backward/shift tabbing targets the logical element prior to the target. Finally, `modal` will open the content in a tab order fully separate from the original content flow and trap the tab order within that content until the required interaction is complete.
59-
60-
## Examples
61-
62-
Here a default `<overlay-trigger>` manages content that is triggered by click and "hover" interactions.
63-
64-
```html
65-
<overlay-trigger id="trigger" placement="bottom" offset="6">
66-
<sp-button variant="primary" slot="trigger">Button popover</sp-button>
67-
<sp-popover slot="click-content" direction="bottom" tip>
68-
<sp-dialog no-divider class="options-popover-content">
69-
<sp-slider
70-
value="5"
71-
step="0.5"
72-
min="0"
73-
max="20"
74-
label="Awesomeness"
75-
></sp-slider>
76-
<sp-button>Press me</sp-button>
77-
</sp-dialog>
78-
</sp-popover>
79-
<sp-tooltip slot="hover-content" delayed>Tooltip</sp-tooltip>
80-
<sp-popover slot="longpress-content" tip>
81-
<sp-action-group
82-
selects="single"
83-
vertical
84-
style="margin: calc(var(--spectrum-spacing-100) / 2);"
85-
>
86-
<sp-action-button>
87-
<sp-icon-magnify slot="icon"></sp-icon-magnify>
88-
</sp-action-button>
89-
<sp-action-button>
90-
<sp-icon-magnify slot="icon"></sp-icon-magnify>
91-
</sp-action-button>
92-
<sp-action-button>
93-
<sp-icon-magnify slot="icon"></sp-icon-magnify>
94-
</sp-action-button>
95-
</sp-action-group>
96-
</sp-popover>
97-
</overlay-trigger>
98-
```
99-
100-
### Click content only
101-
102-
This example only delivers content via the "click" interaction and leverages both `placement` and `type` attributes to customize the visual relationship of the content to the page and its position in the tab order.
54+
In this example, a default `<overlay-trigger>` manages content that is triggered by "click" and "hover" interactions.
10355

10456
```html
10557
<overlay-trigger placement="top" type="replace">
@@ -120,22 +72,96 @@ This example only delivers content via the "click" interaction and leverages bot
12072
</sp-button>
12173
</sp-dialog>
12274
</sp-popover>
75+
<sp-tooltip slot="hover-content">Hover content</sp-tooltip>
12376
</overlay-trigger>
12477
```
12578

126-
### "Hover" content only
79+
### Options
80+
81+
#### Placement
82+
83+
When using the `placement` attribute of an `<overlay-trigger>` (`"top" |"top-start" | "top-end" | "bottom" | "bottom-start" | "bottom-end" | "right" | "right-start" | "right-end" | "left" | "left-start" | "left-end"`), you can suggest to the overlay in which direction relative to the trigger that the content should display. When there is adequate room for the content to display in the specified direction, it will do so. When adequate room is not available, the overlaid content will calculate the direction in which it has the most room to be displayed and use that direction.
84+
85+
#### Type
12786

128-
The delivery of hover content can be customized via the `placement` attribute. However, this content can not be interacted with, so the `type` attribute will not customize its delivery in any way.
87+
<sp-tabs selected="inline" auto label="Type attribute options">
88+
<sp-tab value="inline">Inline</sp-tab>
89+
<sp-tab-panel value="inline">
90+
91+
`'inline'` type inserts the overlay after the trigger in the tab order. This creates a natural flow where:
92+
93+
- Forward tab: Goes to the next logical element
94+
- Backward tab (shift): Returns to the trigger
12995

13096
```html
131-
<overlay-trigger placement="right">
132-
<sp-button slot="trigger">Overlay Trigger</sp-button>
133-
<sp-tooltip slot="hover-content" open placement="right">
134-
Hover Content
135-
</sp-tooltip>
97+
<overlay-trigger type="inline" placement="bottom">
98+
<sp-button slot="trigger">Open Menu</sp-button>
99+
<sp-popover slot="click-content">
100+
<sp-menu>
101+
<sp-menu-item>Option 1</sp-menu-item>
102+
<sp-menu-item>Option 2</sp-menu-item>
103+
</sp-menu>
104+
</sp-popover>
105+
</overlay-trigger>
106+
```
107+
108+
</sp-tab-panel>
109+
<sp-tab value="replace">Replace</sp-tab>
110+
<sp-tab-panel value="replace">
111+
112+
`'replace'` type inserts the overlay as if it were the trigger itself in the tab order. This means:
113+
114+
- Forward tab: Goes to the next logical element
115+
- Backward tab (shift): Goes to the element before the trigger
116+
117+
```html
118+
<overlay-trigger type="replace" placement="bottom">
119+
<sp-button slot="trigger">Show Details</sp-button>
120+
<sp-popover slot="click-content">
121+
<sp-dialog>
122+
<p>Details panel that replaces trigger in tab order</p>
123+
<sp-button
124+
onclick="this.dispatchEvent(new Event('close', { bubbles: true, composed: true }))"
125+
>
126+
Close
127+
</sp-button>
128+
</sp-dialog>
129+
</sp-popover>
130+
</overlay-trigger>
131+
```
132+
133+
</sp-tab-panel>
134+
<sp-tab value="modal">Modal</sp-tab>
135+
<sp-tab-panel value="modal">
136+
137+
`'modal'` type creates a separate tab order and traps focus within the overlay content until the required interaction is complete. This is ideal for important interactions that need user attention.
138+
139+
```html
140+
<overlay-trigger type="modal">
141+
<sp-button slot="trigger">Open Settings</sp-button>
142+
<sp-dialog-wrapper
143+
slot="click-content"
144+
headline="Settings"
145+
dismissable
146+
underlay
147+
>
148+
<sp-field-label>Theme</sp-field-label>
149+
<sp-picker>
150+
<sp-menu-item>Light</sp-menu-item>
151+
<sp-menu-item>Dark</sp-menu-item>
152+
</sp-picker>
153+
<sp-button
154+
onclick="this.dispatchEvent(new Event('close', { bubbles: true, composed: true }))"
155+
>
156+
Save
157+
</sp-button>
158+
</sp-dialog-wrapper>
136159
</overlay-trigger>
137160
```
138161

162+
</sp-tab-panel>
163+
</sp-tabs>
164+
139165
### Performance optimization
140166

141167
The `triggered-by` attribute (`triggeredBy` property) allows you to explicitly declare which types of overlays your implementation will use. This can help optimize performance by avoiding unnecessary DOM operations and preventing race conditions during rendering.
@@ -170,6 +196,6 @@ The `triggered-by` attribute accepts a space-separated string of overlay types:
170196

171197
When not specified, the component will automatically detect which content types are present, but this may result in additional rendering cycles. For optimal performance, especially in applications with many overlay triggers, explicitly declaring the content types you plan to use is recommended.
172198

173-
## Accessibility
199+
### Accessibility
174200

175201
When using an `<overlay-trigger>` element, it is important to be sure the that content you project into `slot="trigger"` is "interactive". This means that an element within that branch of DOM will be able to receive focus, and said element will appropriately convert keyboard interactions to `click` events, similar to what you'd find with `<a href="#">Anchors</a>`, `<button>Buttons</button>`, etc. You can find further reading on the subject of accessible keyboard interactions at [https://www.w3.org/WAI/WCAG21/Understanding/keyboard](https://www.w3.org/WAI/WCAG21/Understanding/keyboard).

0 commit comments

Comments
 (0)