@justeattakeaway/pie-tooltip 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +99 -33
- package/custom-elements.json +136 -6
- package/dist/index.d.ts +27 -56
- package/dist/index.js +352 -240
- package/dist/react.d.ts +27 -56
- package/dist/react.js +1 -1
- package/package.json +4 -4
- package/src/defs.ts +14 -54
- package/src/index.ts +338 -95
- package/src/react.ts +1 -1
- package/src/tooltip.scss +8 -1
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
- [Documentation](#documentation)
|
|
16
16
|
- [Controlled component](#controlled-component)
|
|
17
17
|
- [Properties](#properties)
|
|
18
|
+
- [Methods](#methods)
|
|
18
19
|
- [Slots](#slots)
|
|
19
20
|
- [Events](#events)
|
|
20
21
|
- [CSS Variables](#css-variables)
|
|
@@ -47,16 +48,22 @@ Ideally, you should install the component using the **`@justeattakeaway/pie-webc
|
|
|
47
48
|
|---|---|---|---|
|
|
48
49
|
| `trigger` | Any string | The `id` of the element the panel is anchored to. The trigger lives elsewhere in the DOM and is never slotted into the tooltip. | `undefined` |
|
|
49
50
|
| `isOpen` | `true`, `false` | When true, the panel is visible. The component never writes to this property. | `false` |
|
|
50
|
-
| `position` | `top`, `top-start`, `top-end`, `bottom`, `bottom-start`, `bottom-end`, `left`, `left-start`, `left-end`, `right`, `right-start`, `right-end` | The side of the trigger the panel sits on, and its alignment along the cross axis. | `top` |
|
|
51
|
+
| `position` | `top`, `top-start`, `top-end`, `bottom`, `bottom-start`, `bottom-end`, `left`, `left-start`, `left-end`, `right`, `right-start`, `right-end` | The preferred side of the trigger the panel sits on, and its alignment along the cross axis. The panel repositions itself when this would collide with the viewport or a clipping scroll container. | `top` |
|
|
51
52
|
| `size` | `default`, `fit-to-content`, `fill-container` | How the panel sizes itself. `default` is a fixed 280px and wraps, `fit-to-content` is as wide as its content, and `fill-container` matches the inline size of the trigger's parent element. Not applied when `type` is `icon`. | `default` |
|
|
52
53
|
| `variant` | `default`, `inverse` | The colour treatment of the panel. `default` is the dark panel, `inverse` the light one. | `default` |
|
|
53
54
|
| `type` | `default`, `icon` | The presentation of the panel. `icon` is the compact treatment intended for icon triggers: it has no arrow and is always as wide as its content, so `size` and `--tooltip-width` have no effect on it. | `default` |
|
|
54
|
-
| `isDismissible` | `true`, `false` | When true, a close button is rendered inside the panel. | `false` |
|
|
55
|
+
| `isDismissible` | `true`, `false` | When true, a close button is rendered inside the panel, and the panel presents as a non-modal dialog, so it needs `heading` or `aria.label` for its accessible name. | `false` |
|
|
55
56
|
| `heading` | Any string | The text to display in the panel's heading. In dialog mode this also provides the panel's accessible name. | `undefined` |
|
|
56
57
|
| `headingLevel` | `h2`, `h3`, `h4`, `h5`, `h6` | The HTML heading tag to use for the panel's heading. | `h2` |
|
|
57
58
|
| `aria` | `{ close?: string, label?: string }` | `close` names the close button. `label` names the panel in dialog mode when no `heading` is provided. | `undefined` |
|
|
58
59
|
| `triggers` | Array of `hover`, `focus`, `click` | Which interactions request that the panel opens and closes. A configured interaction emits an event; it never changes the panel's state on its own. Empty by default, so no interaction is watched at all. Configure `hover` and `focus` together for keyboard reachability. | `[]` |
|
|
59
60
|
|
|
61
|
+
### Methods
|
|
62
|
+
|
|
63
|
+
| Method | Returns | Description |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `focusPanel()` | `Promise<boolean>` | Moves focus to the panel's content in dialog mode, so screen readers announce the content, followed by the dialog's name and role, once each. Only needed when the panel contains interactive elements, such as a close button or an action button, which make it a dialog. Call it straight after setting `isOpen`: it waits for the panel's opening update to commit, then retries the focus move until it lands. Resolves `true` once focus is in place, or `false` if the panel is closed or in tooltip mode. The content is `tabindex="-1"`, so it is never reached by Tab. See [Managing focus](#managing-focus). |
|
|
66
|
+
|
|
60
67
|
### Slots
|
|
61
68
|
|
|
62
69
|
| Slot | Description |
|
|
@@ -69,7 +76,7 @@ Ideally, you should install the component using the **`@justeattakeaway/pie-webc
|
|
|
69
76
|
| Event | Type | Description |
|
|
70
77
|
|---|---|---|
|
|
71
78
|
| `pie-tooltip-open` | `Event` | Emitted when a configured trigger asks for the panel. Set `isOpen` to `true` in response. Bubbles and is composed. |
|
|
72
|
-
| `pie-tooltip-close` | `Event` | Emitted when the close button is clicked, or
|
|
79
|
+
| `pie-tooltip-close` | `Event` | Emitted when the close button is clicked, Escape is pressed, or a configured trigger asks to dismiss the panel. Set `isOpen` to `false` in response. Bubbles and is composed. |
|
|
73
80
|
|
|
74
81
|
### CSS Variables
|
|
75
82
|
|
|
@@ -86,7 +93,7 @@ Set both on the `pie-tooltip` element itself.
|
|
|
86
93
|
|
|
87
94
|
## Positioning
|
|
88
95
|
|
|
89
|
-
Place the tooltip next to its trigger element in the DOM for the best accessibility practice. The `position`
|
|
96
|
+
Place the tooltip next to its trigger element in the DOM for the best accessibility practice. The `position` property will place the tooltip near to the trigger based on which value is provided.
|
|
90
97
|
|
|
91
98
|
`position` names a side and, optionally, an alignment along the opposite axis:
|
|
92
99
|
|
|
@@ -99,6 +106,17 @@ right right-start right-end
|
|
|
99
106
|
|
|
100
107
|
In right-to-left languages, everything on the inline axis mirrors. The alignments follow the reading direction, so `top-start` aligns against the right-hand edge, and `left` and `right` swap: a panel asked for on the left appears on the right. The `-start` and `-end` alignments of `left` and `right` are on the block axis, which has no direction to mirror, so only the side moves.
|
|
101
108
|
|
|
109
|
+
### Collision detection
|
|
110
|
+
|
|
111
|
+
`position` is a preference, not a guarantee. Before the panel is shown, and on every scroll, resize or direction change while it is open, the component measures the panel against the space available and repositions it if the preferred position would collide.
|
|
112
|
+
|
|
113
|
+
- It flips to the opposite side first: `top` to `bottom`, and so on.
|
|
114
|
+
- It then tries the remaining sides.
|
|
115
|
+
- Within a side, it shifts the alignment (for example `top-start` to `top-end`) so the panel stays fully in view.
|
|
116
|
+
- If no position fits entirely, it uses whichever position shows the most of the panel.
|
|
117
|
+
|
|
118
|
+
The available space is the viewport, narrowed by any ancestor that clips the panel. Collision detection is always on and cannot be disabled.
|
|
119
|
+
|
|
102
120
|
## Sizing
|
|
103
121
|
|
|
104
122
|
| `size` | Behaviour |
|
|
@@ -115,25 +133,26 @@ In right-to-left languages, everything on the inline axis mirrors. The alignment
|
|
|
115
133
|
|
|
116
134
|
The panel presents as one of two patterns, inferred from the `action` slot contents. They carry different obligations.
|
|
117
135
|
|
|
118
|
-
| | `action` slot empty | `action` slot filled |
|
|
136
|
+
| | `action` slot empty and not dismissible | `action` slot filled or `isDismissible` |
|
|
119
137
|
|---|---|---|
|
|
120
138
|
| Panel role | `tooltip` | `dialog` |
|
|
121
139
|
| Contains focusable content | No | Yes |
|
|
122
140
|
| Accessible name on panel | None | Required, from `heading` or `aria.label` |
|
|
123
141
|
| In the accessibility tree while closed | Yes, as the trigger's description | No |
|
|
124
142
|
|
|
125
|
-
A close button
|
|
143
|
+
A close button makes the panel a dialog: it invites the user inside, and a panel the user enters is announced through focus, not through a description. The same applies to any panel toggled by a click or a tap, so use the `action` slot there. Tooltip mode is for hover- and focus-followed panels only.
|
|
126
144
|
|
|
127
145
|
### What the component does
|
|
128
146
|
|
|
129
|
-
- Sets `role="tooltip"` or `role="dialog"` from the `action` slot
|
|
147
|
+
- Sets `role="tooltip"` or `role="dialog"` from the `action` slot and `isDismissible`, resolved on the client before the first paint.
|
|
130
148
|
- Names the dialog panel from `heading`, falling back to `aria.label`.
|
|
131
|
-
-
|
|
149
|
+
- Exposes `focusPanel()` for dialog mode, which moves focus to the panel's content so the content, followed by the dialog's name and role, are announced once each on every screen reader. The panel carries no `aria-describedby`; see [Managing focus](#managing-focus).
|
|
150
|
+
- Removes the dialog panel from the accessibility tree while closed. In tooltip mode the panel stays in the DOM, so a description referring to the tooltip still resolves.
|
|
132
151
|
- Names the close button from `aria.close` and places it in the tab sequence inside the panel.
|
|
133
152
|
- Keeps the panel clear of the trigger at every placement, so the panel cannot obscure a focused trigger (WCAG 2.4.11).
|
|
134
153
|
- Wraps content.
|
|
135
154
|
|
|
136
|
-
It does not touch the trigger, and it does not move focus. The component never writes attributes to the element named by `trigger
|
|
155
|
+
It does not touch the trigger, and it does not move focus on its own; `focusPanel()` moves it only when you call it. The component never writes attributes to the element named by `trigger`. See [Wiring the trigger](#wiring-the-trigger) and [Managing focus](#managing-focus).
|
|
137
156
|
|
|
138
157
|
### What you need to do
|
|
139
158
|
|
|
@@ -143,8 +162,9 @@ It does not touch the trigger, and it does not move focus. The component never w
|
|
|
143
162
|
- **Use a natively interactive element as the trigger**, a button or a link, so focus and click behave correctly.
|
|
144
163
|
- **Own `isOpen`.** Listen for `pie-tooltip-close` and set `isOpen` to `false` in response.
|
|
145
164
|
- **Keep focusable content out of the `content` slot.** Interactive content belongs in the `action` slot, which switches the panel to a dialog.
|
|
165
|
+
- **Make click-toggled or dismissible panels dialogs.** A panel opened by a click or a tap appears with no focus change, so screen readers stay silent; a close button puts the user inside the panel. Both are dialog interactions, so fill the `action` slot and follow [Managing focus](#managing-focus).
|
|
146
166
|
- **Place `<pie-tooltip>` immediately after its trigger in the DOM.** The component anchors by `id` and can sit anywhere, but reading and tab order follow DOM order.
|
|
147
|
-
- **In dialog mode, provide `heading` or `aria.label`** so the dialog has an accessible name.
|
|
167
|
+
- **In dialog mode, provide `heading` or `aria.label`** so the dialog has an accessible name. This includes every dismissible panel, which is a dialog.
|
|
148
168
|
- **Provide a translated `aria.close`** whenever `isDismissible` is set.
|
|
149
169
|
- **Keep tooltip-mode content short and supplementary.** Anything essential or interactive belongs in dialog mode, or inline in the page.
|
|
150
170
|
|
|
@@ -152,25 +172,50 @@ It does not touch the trigger, and it does not move focus. The component never w
|
|
|
152
172
|
|
|
153
173
|
The trigger lives outside the tooltip and the component leaves it untouched, so you declare the relationship. What to set depends on the mode.
|
|
154
174
|
|
|
175
|
+
> The [Screen readers stories](https://webc.pie.design/?path=/story/components-tooltip-screen-readers--docs) show every wiring in this section as live, runnable examples.
|
|
176
|
+
|
|
155
177
|
| ARIA | Set it when | Value |
|
|
156
178
|
|---|---|---|
|
|
157
179
|
| `haspopup` | Dialog mode, so the trigger announces that it opens a dialog | `dialog` |
|
|
158
180
|
| `expanded` | You toggle the panel from the trigger with a click or a tap | Your `isOpen` value |
|
|
159
|
-
| `describedby` | Tooltip mode, and the trigger is a plain HTML element | The `id` of the
|
|
181
|
+
| `describedby` | Tooltip mode, and the trigger is a plain HTML element | The `id` of the `pie-tooltip` element itself |
|
|
160
182
|
|
|
161
183
|
Leave `expanded` off a hover-only or focus-only panel. Nothing is being toggled, so it has nothing to describe. There is no `controls` in the table because it adds nothing here: the description already carries the relationship, and support for it is patchy.
|
|
162
184
|
|
|
185
|
+
#### Point the description at the tooltip itself
|
|
186
|
+
|
|
187
|
+
In tooltip mode, give the `<pie-tooltip>` element an `id` and set `aria-describedby` on the trigger to that `id`. The tooltip and a plain HTML trigger live in the same tree, so the reference resolves, and the browser reads the panel's text through the tooltip's shadow root. No `id` is needed on the element in the `content` slot.
|
|
188
|
+
|
|
189
|
+
```html
|
|
190
|
+
<button id="delivery-info" aria-describedby="delivery-panel">Delivery times</button>
|
|
191
|
+
|
|
192
|
+
<pie-tooltip id="delivery-panel" trigger="delivery-info">
|
|
193
|
+
<span slot="content">Orders placed before 6pm arrive today.</span>
|
|
194
|
+
</pie-tooltip>
|
|
195
|
+
```
|
|
196
|
+
|
|
163
197
|
#### A description cannot cross a shadow boundary
|
|
164
198
|
|
|
165
|
-
`aria
|
|
199
|
+
`aria-describedby` takes an `id`, and an `id` only resolves inside the tree of the element that references it. The `<button>` inside `pie-icon-button` lives in the component's shadow root, so it cannot see the tooltip's `id` in your document, and `aria.describedby` is unusable for this purpose even though the property exists.
|
|
166
200
|
|
|
167
|
-
There is no way around this from outside the component. When the trigger is a PIE component
|
|
201
|
+
There is no way around this from outside the component. When the trigger is a PIE component, pass the panel's text as the trigger's own description instead. `pie-button` and `pie-icon-button` accept an `aria.description`, which they render as an `aria-description` attribute on their internal element, and a string crosses the shadow boundary where an IDREF cannot:
|
|
168
202
|
|
|
169
|
-
|
|
203
|
+
```js
|
|
204
|
+
trigger.aria = {
|
|
205
|
+
label: 'Delivery times',
|
|
206
|
+
description: 'Orders placed before 6pm arrive today.',
|
|
207
|
+
};
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Keep the name short and let the description carry the panel's text. As with `aria-describedby`, the description must stay in step with the content in the `content` slot.
|
|
211
|
+
|
|
212
|
+
Dialog mode is unaffected: the panel's content is announced when focus moves into it, so it needs no trigger-side description at all.
|
|
213
|
+
|
|
214
|
+
Dialog mode is unaffected: the panel's content is announced when focus moves into it, so it needs no trigger-side description at all.
|
|
170
215
|
|
|
171
216
|
#### A tooltip panel on an icon trigger
|
|
172
217
|
|
|
173
|
-
`hover` and `focus` together give the panel to both pointer and keyboard users. Nothing is toggled, so there is no `expanded
|
|
218
|
+
`hover` and `focus` together give the panel to both pointer and keyboard users. Nothing is toggled, so there is no `expanded`. The trigger is a PIE component, so a description cannot cross the shadow boundary by `id`, so the panel's text travels in the trigger's `aria.description` instead (see [A description cannot cross a shadow boundary](#a-description-cannot-cross-a-shadow-boundary)).
|
|
174
219
|
|
|
175
220
|
```js
|
|
176
221
|
// main.js
|
|
@@ -181,7 +226,10 @@ import '@justeattakeaway/pie-icons-webc/dist/IconInfoCircle.js';
|
|
|
181
226
|
const trigger = document.querySelector('#delivery-info');
|
|
182
227
|
const panel = document.querySelector('#delivery-panel');
|
|
183
228
|
|
|
184
|
-
trigger.aria = {
|
|
229
|
+
trigger.aria = {
|
|
230
|
+
label: 'Delivery times',
|
|
231
|
+
description: 'Orders placed before 6pm arrive today.',
|
|
232
|
+
};
|
|
185
233
|
panel.triggers = ['hover', 'focus'];
|
|
186
234
|
|
|
187
235
|
panel.addEventListener('pie-tooltip-open', () => { panel.isOpen = true; });
|
|
@@ -216,12 +264,13 @@ import { IconInfoCircle } from '@justeattakeaway/pie-icons-webc/dist/react/IconI
|
|
|
216
264
|
export function DeliveryTimes () {
|
|
217
265
|
const [isOpen, setIsOpen] = useState(false);
|
|
218
266
|
const triggerRef = useRef(null);
|
|
219
|
-
const
|
|
267
|
+
const tooltipRef = useRef(null);
|
|
220
268
|
|
|
221
269
|
const open = () => {
|
|
222
270
|
setIsOpen(true);
|
|
223
|
-
//
|
|
224
|
-
|
|
271
|
+
// `focusPanel()` waits for the panel's opening update to commit, then moves focus to
|
|
272
|
+
// the content so screen readers announce it with the dialog's name and role.
|
|
273
|
+
tooltipRef.current?.focusPanel();
|
|
225
274
|
};
|
|
226
275
|
|
|
227
276
|
const close = () => {
|
|
@@ -251,6 +300,7 @@ export function DeliveryTimes () {
|
|
|
251
300
|
</PieIconButton>
|
|
252
301
|
|
|
253
302
|
<PieTooltip
|
|
303
|
+
ref={tooltipRef}
|
|
254
304
|
trigger="delivery-info"
|
|
255
305
|
heading="Delivery times"
|
|
256
306
|
isOpen={isOpen}
|
|
@@ -260,7 +310,7 @@ export function DeliveryTimes () {
|
|
|
260
310
|
onPieTooltipOpen={open}
|
|
261
311
|
onPieTooltipClose={close}>
|
|
262
312
|
<span slot="content">Orders placed before 6pm arrive today.</span>
|
|
263
|
-
<PieButton slot="action" size="xsmall"
|
|
313
|
+
<PieButton slot="action" size="xsmall" onClick={close}>
|
|
264
314
|
Got it
|
|
265
315
|
</PieButton>
|
|
266
316
|
</PieTooltip>
|
|
@@ -275,9 +325,7 @@ The `closest('pie-tooltip')` check works because `document.activeElement` report
|
|
|
275
325
|
|
|
276
326
|
#### Driving the panel without `triggers`
|
|
277
327
|
|
|
278
|
-
Leave `triggers` unset when the panel's timing is not an interaction with its trigger, such as a step in an onboarding tour. Nothing is watched, so `pie-tooltip-open` never fires and `expanded` has nothing to describe. The close button still
|
|
279
|
-
|
|
280
|
-
Escape is watched only while at least one trigger is configured, so a panel driven this way needs its own key handling if you want Escape to dismiss it.
|
|
328
|
+
Leave `triggers` unset when the panel's timing is not an interaction with its trigger, such as a step in an onboarding tour. Nothing is watched, so `pie-tooltip-open` never fires and `expanded` has nothing to describe. The close button and Escape still emit `pie-tooltip-close`.
|
|
281
329
|
|
|
282
330
|
```html
|
|
283
331
|
<template>
|
|
@@ -302,24 +350,27 @@ Escape is watched only while at least one trigger is configured, so a panel driv
|
|
|
302
350
|
|
|
303
351
|
### Managing focus
|
|
304
352
|
|
|
305
|
-
In tooltip mode there is nothing to do. A tooltip must not take focus, and
|
|
353
|
+
In tooltip mode there is nothing to do. A tooltip must not take focus, and a panel that is dismissible or click-toggled is not a tooltip, so it is a dialog and the focus contract below applies to it.
|
|
306
354
|
|
|
307
355
|
In dialog mode you own two moments:
|
|
308
356
|
|
|
309
|
-
- **On open,
|
|
357
|
+
- **On open, call `focusPanel()`.** It moves focus to the content carrying the panel's descriptive text, so screen readers announce the content, followed by the dialog's name and role. It waits for the panel's opening update to commit, then retries the focus move until it lands, and resolves to `true` once focus is in place, or `false` if the panel is closed or in tooltip mode. No waiting on your side is needed: call it straight after setting `isOpen`. Only needed when the panel contains interactive elements, such as a close button or an action button, which make it a dialog.
|
|
358
|
+
|
|
359
|
+
The heading names the panel through `aria-labelledby`; the content is announced by the focus move itself. The panel carries no `aria-describedby`: VoiceOver never announces a dialog's description on focus entry ([WebKit bug 282773](https://bugs.webkit.org/show_bug.cgi?id=282773)), and NVDA and JAWS announce it in addition to the focused content, so a description either does nothing or says the content twice. This follows the [WAI-ARIA Authoring Practices Guide](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/#keyboard-interaction)'s static-text focus recommendation: the content is `tabindex="-1"`, never reached by Tab, and the panel's own controls stay next in the tab sequence. If you move focus anywhere else, the content is not announced on open, though it stays readable inside the dialog.
|
|
360
|
+
|
|
310
361
|
- **On close, put focus back**, but only if focus was still inside the panel. Closing on a hover-away or a click elsewhere must not pull focus away from whatever the user has moved on to.
|
|
311
362
|
|
|
312
363
|
## Usage Examples
|
|
313
364
|
|
|
365
|
+
> The examples below are for illustration only and are not production ready. They are kept deliberately minimal: wire up error handling, state management and focus behaviour as your application requires.
|
|
366
|
+
|
|
314
367
|
**For HTML:**
|
|
315
368
|
|
|
369
|
+
The trigger below is a plain HTML button, so the wiring is the trigger's own `aria-describedby` pointing at the tooltip's `id`.
|
|
370
|
+
|
|
316
371
|
```js
|
|
317
372
|
// import as module into a js file e.g. main.js
|
|
318
373
|
import '@justeattakeaway/pie-webc/components/tooltip.js'
|
|
319
|
-
import '@justeattakeaway/pie-webc/components/button.js'
|
|
320
|
-
|
|
321
|
-
// `aria` takes an object, so it is set as a property rather than an attribute.
|
|
322
|
-
document.querySelector('#delivery-panel').aria = { close: 'Close' };
|
|
323
374
|
```
|
|
324
375
|
|
|
325
376
|
```html
|
|
@@ -329,13 +380,15 @@ document.querySelector('#delivery-panel').aria = { close: 'Close' };
|
|
|
329
380
|
```
|
|
330
381
|
|
|
331
382
|
```html
|
|
332
|
-
<
|
|
383
|
+
<button id="delivery-info" aria-describedby="delivery-panel">Delivery times</button>
|
|
333
384
|
|
|
334
385
|
<pie-tooltip id="delivery-panel" trigger="delivery-info" isOpen isDismissible>
|
|
335
386
|
<span slot="content">Orders placed before 6pm arrive today.</span>
|
|
336
387
|
</pie-tooltip>
|
|
337
388
|
```
|
|
338
389
|
|
|
390
|
+
When the trigger is a PIE component such as `pie-button`, an IDREF cannot cross its shadow boundary, so pass the text through the trigger's `aria` property with `description` instead.
|
|
391
|
+
|
|
339
392
|
**For Native JS Applications, Vue, Angular, Svelte etc.:**
|
|
340
393
|
|
|
341
394
|
```js
|
|
@@ -345,9 +398,14 @@ import '@justeattakeaway/pie-webc/components/tooltip.js'
|
|
|
345
398
|
|
|
346
399
|
```html
|
|
347
400
|
<template>
|
|
348
|
-
<pie-button
|
|
401
|
+
<pie-button
|
|
402
|
+
id="delivery-info"
|
|
403
|
+
:aria="{ label: 'Delivery times', description: 'Orders placed before 6pm arrive today.' }">
|
|
404
|
+
Delivery times
|
|
405
|
+
</pie-button>
|
|
349
406
|
|
|
350
407
|
<pie-tooltip
|
|
408
|
+
id="delivery-panel"
|
|
351
409
|
trigger="delivery-info"
|
|
352
410
|
:isOpen="isOpen"
|
|
353
411
|
isDismissible
|
|
@@ -358,6 +416,8 @@ import '@justeattakeaway/pie-webc/components/tooltip.js'
|
|
|
358
416
|
</template>
|
|
359
417
|
```
|
|
360
418
|
|
|
419
|
+
The trigger is a PIE component, so the text travels in its `aria.description` rather than `aria-describedby` (see [A description cannot cross a shadow boundary](#a-description-cannot-cross-a-shadow-boundary)).
|
|
420
|
+
|
|
361
421
|
**For React Applications:**
|
|
362
422
|
|
|
363
423
|
```jsx
|
|
@@ -370,9 +430,15 @@ export function DeliveryTimes () {
|
|
|
370
430
|
|
|
371
431
|
return (
|
|
372
432
|
<>
|
|
373
|
-
|
|
433
|
+
{/* A PIE component trigger carries the text in its description, not `aria-describedby`. */}
|
|
434
|
+
<PieButton
|
|
435
|
+
id="delivery-info"
|
|
436
|
+
aria={{ label: 'Delivery times', description: 'Orders placed before 6pm arrive today.' }}>
|
|
437
|
+
Delivery times
|
|
438
|
+
</PieButton>
|
|
374
439
|
|
|
375
440
|
<PieTooltip
|
|
441
|
+
id="delivery-panel"
|
|
376
442
|
trigger="delivery-info"
|
|
377
443
|
isOpen={isOpen}
|
|
378
444
|
isDismissible
|
|
@@ -402,7 +468,7 @@ document.querySelector('#delivery-info').aria = {
|
|
|
402
468
|
<icon-info-circle></icon-info-circle>
|
|
403
469
|
</pie-icon-button>
|
|
404
470
|
|
|
405
|
-
<pie-tooltip trigger="delivery-info" isOpen heading="Delivery times">
|
|
471
|
+
<pie-tooltip id="delivery-panel" trigger="delivery-info" isOpen heading="Delivery times">
|
|
406
472
|
<span slot="content">Orders placed before 6pm arrive today.</span>
|
|
407
473
|
<pie-button slot="action" size="xsmall">Next</pie-button>
|
|
408
474
|
</pie-tooltip>
|
package/custom-elements.json
CHANGED
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"text": "['tooltip', 'dialog']"
|
|
68
68
|
},
|
|
69
69
|
"default": "['tooltip', 'dialog']",
|
|
70
|
-
"description": "The two patterns the panel can present as
|
|
70
|
+
"description": "The two patterns the panel can present as, inferred from the `action` slot."
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
"kind": "variable",
|
|
@@ -343,6 +343,14 @@
|
|
|
343
343
|
"privacy": "private",
|
|
344
344
|
"default": "true"
|
|
345
345
|
},
|
|
346
|
+
{
|
|
347
|
+
"kind": "field",
|
|
348
|
+
"name": "_resolvedPosition",
|
|
349
|
+
"type": {
|
|
350
|
+
"text": "TooltipProps['position'] | undefined"
|
|
351
|
+
},
|
|
352
|
+
"privacy": "private"
|
|
353
|
+
},
|
|
346
354
|
{
|
|
347
355
|
"kind": "field",
|
|
348
356
|
"name": "_clippedTriggerElement",
|
|
@@ -361,6 +369,33 @@
|
|
|
361
369
|
"privacy": "private",
|
|
362
370
|
"default": "[]"
|
|
363
371
|
},
|
|
372
|
+
{
|
|
373
|
+
"kind": "field",
|
|
374
|
+
"name": "_overlayClippers",
|
|
375
|
+
"type": {
|
|
376
|
+
"text": "Array<Element>"
|
|
377
|
+
},
|
|
378
|
+
"privacy": "private",
|
|
379
|
+
"default": "[]"
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"kind": "field",
|
|
383
|
+
"name": "_collisionSignature",
|
|
384
|
+
"type": {
|
|
385
|
+
"text": "string | null"
|
|
386
|
+
},
|
|
387
|
+
"privacy": "private",
|
|
388
|
+
"default": "null"
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
"kind": "field",
|
|
392
|
+
"name": "_overlayModeDirty",
|
|
393
|
+
"type": {
|
|
394
|
+
"text": "boolean"
|
|
395
|
+
},
|
|
396
|
+
"privacy": "private",
|
|
397
|
+
"default": "true"
|
|
398
|
+
},
|
|
364
399
|
{
|
|
365
400
|
"kind": "field",
|
|
366
401
|
"name": "_triggerTrackingController",
|
|
@@ -404,7 +439,15 @@
|
|
|
404
439
|
},
|
|
405
440
|
{
|
|
406
441
|
"kind": "field",
|
|
407
|
-
"name": "
|
|
442
|
+
"name": "_hoverCloseTimer",
|
|
443
|
+
"type": {
|
|
444
|
+
"text": "ReturnType<typeof setTimeout> | undefined"
|
|
445
|
+
},
|
|
446
|
+
"privacy": "private"
|
|
447
|
+
},
|
|
448
|
+
{
|
|
449
|
+
"kind": "field",
|
|
450
|
+
"name": "_openedByClick",
|
|
408
451
|
"type": {
|
|
409
452
|
"text": "boolean"
|
|
410
453
|
},
|
|
@@ -413,11 +456,18 @@
|
|
|
413
456
|
},
|
|
414
457
|
{
|
|
415
458
|
"kind": "field",
|
|
416
|
-
"name": "
|
|
459
|
+
"name": "_instanceId",
|
|
460
|
+
"privacy": "private",
|
|
461
|
+
"readonly": true
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
"kind": "field",
|
|
465
|
+
"name": "_headingId",
|
|
417
466
|
"type": {
|
|
418
|
-
"text": "
|
|
467
|
+
"text": "string"
|
|
419
468
|
},
|
|
420
|
-
"privacy": "private"
|
|
469
|
+
"privacy": "private",
|
|
470
|
+
"readonly": true
|
|
421
471
|
},
|
|
422
472
|
{
|
|
423
473
|
"kind": "field",
|
|
@@ -428,6 +478,16 @@
|
|
|
428
478
|
"privacy": "private",
|
|
429
479
|
"readonly": true
|
|
430
480
|
},
|
|
481
|
+
{
|
|
482
|
+
"kind": "method",
|
|
483
|
+
"name": "focusPanel",
|
|
484
|
+
"privacy": "public",
|
|
485
|
+
"return": {
|
|
486
|
+
"type": {
|
|
487
|
+
"text": "Promise<boolean>"
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
},
|
|
431
491
|
{
|
|
432
492
|
"kind": "method",
|
|
433
493
|
"name": "startTrackingTrigger",
|
|
@@ -478,6 +538,76 @@
|
|
|
478
538
|
}
|
|
479
539
|
}
|
|
480
540
|
},
|
|
541
|
+
{
|
|
542
|
+
"kind": "method",
|
|
543
|
+
"name": "resolveCollision",
|
|
544
|
+
"privacy": "private",
|
|
545
|
+
"return": {
|
|
546
|
+
"type": {
|
|
547
|
+
"text": "void"
|
|
548
|
+
}
|
|
549
|
+
},
|
|
550
|
+
"parameters": [
|
|
551
|
+
{
|
|
552
|
+
"name": "anchorRect",
|
|
553
|
+
"type": {
|
|
554
|
+
"text": "DOMRect"
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
]
|
|
558
|
+
},
|
|
559
|
+
{
|
|
560
|
+
"kind": "method",
|
|
561
|
+
"name": "_setResolvedPosition",
|
|
562
|
+
"privacy": "private",
|
|
563
|
+
"return": {
|
|
564
|
+
"type": {
|
|
565
|
+
"text": "void"
|
|
566
|
+
}
|
|
567
|
+
},
|
|
568
|
+
"parameters": [
|
|
569
|
+
{
|
|
570
|
+
"name": "position",
|
|
571
|
+
"type": {
|
|
572
|
+
"text": "TooltipProps['position']"
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
]
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
"kind": "method",
|
|
579
|
+
"name": "_getCollisionBoundary",
|
|
580
|
+
"privacy": "private",
|
|
581
|
+
"return": {
|
|
582
|
+
"type": {
|
|
583
|
+
"text": "DOMRect | null"
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
"kind": "method",
|
|
589
|
+
"name": "_getCandidatePositions",
|
|
590
|
+
"privacy": "private",
|
|
591
|
+
"return": {
|
|
592
|
+
"type": {
|
|
593
|
+
"text": "Array<{ side: TooltipSide; alignment: TooltipAlignment }>"
|
|
594
|
+
}
|
|
595
|
+
},
|
|
596
|
+
"parameters": [
|
|
597
|
+
{
|
|
598
|
+
"name": "preferredSide",
|
|
599
|
+
"type": {
|
|
600
|
+
"text": "TooltipSide"
|
|
601
|
+
}
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
"name": "preferredAlignment",
|
|
605
|
+
"type": {
|
|
606
|
+
"text": "TooltipAlignment"
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
]
|
|
610
|
+
},
|
|
481
611
|
{
|
|
482
612
|
"kind": "method",
|
|
483
613
|
"name": "_refreshTriggerClippers",
|
|
@@ -601,7 +731,7 @@
|
|
|
601
731
|
"type": {
|
|
602
732
|
"text": "Event"
|
|
603
733
|
},
|
|
604
|
-
"description": "When the close button is clicked, or a configured trigger asks to dismiss the panel. Set `isOpen` to `false` in response.",
|
|
734
|
+
"description": "When the close button is clicked, Escape is pressed, or a configured trigger asks to dismiss the panel. Set `isOpen` to `false` in response.",
|
|
605
735
|
"name": "pie-tooltip-close"
|
|
606
736
|
}
|
|
607
737
|
],
|