@justeattakeaway/pie-tooltip 0.1.1 → 0.3.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 +344 -15
- package/custom-elements.json +644 -3
- package/dist/index.d.ts +153 -2
- package/dist/index.js +390 -18
- package/dist/react.d.ts +159 -3
- package/dist/react.js +25 -7
- package/package.json +6 -4
- package/src/defs.ts +129 -3
- package/src/index.ts +691 -9
- package/src/react.ts +11 -3
- package/src/tooltip.scss +408 -2
package/README.md
CHANGED
|
@@ -7,16 +7,20 @@
|
|
|
7
7
|
</a>
|
|
8
8
|
</p>
|
|
9
9
|
|
|
10
|
-
`@justeattakeaway/pie-tooltip` is a Web Component built using the Lit library. It
|
|
10
|
+
`@justeattakeaway/pie-tooltip` is a Web Component built using the Lit library. It provides an accessible panel that is anchored to a trigger elsewhere on the page.
|
|
11
11
|
|
|
12
12
|
## Table of Contents
|
|
13
13
|
|
|
14
14
|
- [Installation](#installation)
|
|
15
15
|
- [Documentation](#documentation)
|
|
16
|
+
- [Controlled component](#controlled-component)
|
|
16
17
|
- [Properties](#properties)
|
|
17
18
|
- [Slots](#slots)
|
|
18
|
-
- [CSS Variables](#css-variables)
|
|
19
19
|
- [Events](#events)
|
|
20
|
+
- [CSS Variables](#css-variables)
|
|
21
|
+
- [Positioning](#positioning)
|
|
22
|
+
- [Sizing](#sizing)
|
|
23
|
+
- [Accessibility](#accessibility)
|
|
20
24
|
- [Usage Examples](#usage-examples)
|
|
21
25
|
- [Questions and Support](#questions-and-support)
|
|
22
26
|
- [Contributing](#contributing)
|
|
@@ -29,25 +33,281 @@ Ideally, you should install the component using the **`@justeattakeaway/pie-webc
|
|
|
29
33
|
|
|
30
34
|
## Documentation
|
|
31
35
|
|
|
36
|
+
### Controlled component
|
|
37
|
+
|
|
38
|
+
`pie-tooltip` is a controlled component. It never writes to its own `isOpen`, and it never opens or closes itself.
|
|
39
|
+
|
|
40
|
+
1. You own `isOpen`.
|
|
41
|
+
2. You listen for `pie-tooltip-open` and `pie-tooltip-close`.
|
|
42
|
+
3. You pass the value back to open/close the tooltip.
|
|
43
|
+
|
|
32
44
|
### Properties
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
45
|
+
|
|
46
|
+
| Prop | Options | Description | Default |
|
|
47
|
+
|---|---|---|---|
|
|
48
|
+
| `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
|
+
| `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
|
+
| `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
|
+
| `variant` | `default`, `inverse` | The colour treatment of the panel. `default` is the dark panel, `inverse` the light one. | `default` |
|
|
53
|
+
| `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
|
+
| `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
|
+
| `headingLevel` | `h2`, `h3`, `h4`, `h5`, `h6` | The HTML heading tag to use for the panel's heading. | `h2` |
|
|
57
|
+
| `aria` | `{ close?: string, label?: string }` | `close` names the close button. `label` names the panel in dialog mode when no `heading` is provided. | `undefined` |
|
|
58
|
+
| `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. | `[]` |
|
|
36
59
|
|
|
37
60
|
### Slots
|
|
38
|
-
| Slot | Description |
|
|
39
|
-
|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
40
|
-
| | |
|
|
41
61
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
|
62
|
+
| Slot | Description |
|
|
63
|
+
|---|---|
|
|
64
|
+
| `content` | The descriptive content of the panel. Must not contain focusable elements. |
|
|
65
|
+
| `action` | Designed for using `pie-button`. Filling this slot switches the panel from a tooltip to a non-modal dialog. When using `pie-button` always set the size to `xsmall`.|
|
|
46
66
|
|
|
47
67
|
### Events
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
68
|
+
|
|
69
|
+
| Event | Type | Description |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| `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 when a configured trigger asks to dismiss the panel. Set `isOpen` to `false` in response. Bubbles and is composed. |
|
|
73
|
+
|
|
74
|
+
### CSS Variables
|
|
75
|
+
|
|
76
|
+
| Variable | Description | Default |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| `--tooltip-offset` | The gap between the trigger and the arrow's tip, or between the trigger and the panel edge when `type` is `icon`. | `var(--dt-spacing-a)` |
|
|
79
|
+
| `--tooltip-width` | Sets the panel's inline size directly, overriding whatever `size` would have produced. Accepts any length. Ignored when `type` is `icon`. | Unset |
|
|
80
|
+
|
|
81
|
+
Set both on the `pie-tooltip` element itself.
|
|
82
|
+
|
|
83
|
+
```html
|
|
84
|
+
<pie-tooltip style="--tooltip-offset: 16px;" trigger="delivery-info"></pie-tooltip>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Positioning
|
|
88
|
+
|
|
89
|
+
Place the tooltip next to its trigger element in the DOM for the best accessibility practice. The `position` element will place the tooltip near to the trigger based on which value is provided.
|
|
90
|
+
|
|
91
|
+
`position` names a side and, optionally, an alignment along the opposite axis:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
top top-start top-end
|
|
95
|
+
bottom bottom-start bottom-end
|
|
96
|
+
left left-start left-end
|
|
97
|
+
right right-start right-end
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
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
|
+
|
|
102
|
+
## Sizing
|
|
103
|
+
|
|
104
|
+
| `size` | Behaviour |
|
|
105
|
+
|---|---|
|
|
106
|
+
| `default` | The panel is always 280px wide. Longer content wraps. |
|
|
107
|
+
| `fit-to-content` | The panel is as wide as its content, up to the width of the viewport. |
|
|
108
|
+
| `fill-container` | The panel's inline size matches the inline size of the trigger's parent element, whatever the content. |
|
|
109
|
+
|
|
110
|
+
`--tooltip-width` overrides all three.
|
|
111
|
+
|
|
112
|
+
## Accessibility
|
|
113
|
+
|
|
114
|
+
### The two modes
|
|
115
|
+
|
|
116
|
+
The panel presents as one of two patterns, inferred from the `action` slot contents. They carry different obligations.
|
|
117
|
+
|
|
118
|
+
| | `action` slot empty | `action` slot filled |
|
|
119
|
+
|---|---|---|
|
|
120
|
+
| Panel role | `tooltip` | `dialog` |
|
|
121
|
+
| Contains focusable content | No | Yes |
|
|
122
|
+
| Accessible name on panel | None | Required, from `heading` or `aria.label` |
|
|
123
|
+
| In the accessibility tree while closed | Yes, as the trigger's description | No |
|
|
124
|
+
|
|
125
|
+
A close button does not make the panel a dialog. Only the `action` slot does.
|
|
126
|
+
|
|
127
|
+
### What the component does
|
|
128
|
+
|
|
129
|
+
- Sets `role="tooltip"` or `role="dialog"` from the `action` slot, resolved on the client before the first paint.
|
|
130
|
+
- Names the dialog panel from `heading`, falling back to `aria.label`.
|
|
131
|
+
- Removes the dialog panel from the accessibility tree while closed. In tooltip mode the content stays in the DOM so that a description referring to it still resolves.
|
|
132
|
+
- Names the close button from `aria.close` and places it in the tab sequence inside the panel.
|
|
133
|
+
- Keeps the panel clear of the trigger at every placement, so the panel cannot obscure a focused trigger (WCAG 2.4.11).
|
|
134
|
+
- Wraps content.
|
|
135
|
+
|
|
136
|
+
It does not touch the trigger, and it does not move focus. The component never writes attributes to the element named by `trigger`, and never calls `focus()` on anything. Both are yours to declare: see [Wiring the trigger](#wiring-the-trigger) and [Managing focus](#managing-focus).
|
|
137
|
+
|
|
138
|
+
### What you need to do
|
|
139
|
+
|
|
140
|
+
- **Wire the trigger yourself.** The ARIA attributes that connect the trigger to the panel are yours to set. See [Wiring the trigger](#wiring-the-trigger) for what to set and when.
|
|
141
|
+
- **Move focus yourself in dialog mode.** The panel holds focusable content, so opening it should move focus in and closing it should put focus back. See [Managing focus](#managing-focus).
|
|
142
|
+
- **Give the trigger its own accessible name.** The tooltip is a description and never supplies a name. An icon-only trigger must set its own label; `pie-icon-button` already requires `aria.label`.
|
|
143
|
+
- **Use a natively interactive element as the trigger**, a button or a link, so focus and click behave correctly.
|
|
144
|
+
- **Own `isOpen`.** Listen for `pie-tooltip-close` and set `isOpen` to `false` in response.
|
|
145
|
+
- **Keep focusable content out of the `content` slot.** Interactive content belongs in the `action` slot, which switches the panel to a dialog.
|
|
146
|
+
- **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.
|
|
148
|
+
- **Provide a translated `aria.close`** whenever `isDismissible` is set.
|
|
149
|
+
- **Keep tooltip-mode content short and supplementary.** Anything essential or interactive belongs in dialog mode, or inline in the page.
|
|
150
|
+
|
|
151
|
+
### Wiring the trigger
|
|
152
|
+
|
|
153
|
+
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
|
+
|
|
155
|
+
| ARIA | Set it when | Value |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| `haspopup` | Dialog mode, so the trigger announces that it opens a dialog | `dialog` |
|
|
158
|
+
| `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 element you put in the `content` slot |
|
|
160
|
+
|
|
161
|
+
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
|
+
|
|
163
|
+
#### A description cannot cross a shadow boundary
|
|
164
|
+
|
|
165
|
+
`aria.describedby` takes an `id`, and an `id` only resolves inside the tree of the element that references it. The element you put in the `content` slot stays in your light DOM, so a plain `<button>` in the same document resolves it. The `<button>` inside `pie-icon-button` does not: it cannot see an `id` in your document, so `aria.describedby` is unusable for this purpose even though the property exists.
|
|
166
|
+
|
|
167
|
+
There is no way around this from outside the component. When the trigger is a PIE component and the panel is a plain tooltip, put the information in the trigger's name with `aria.label` instead, as in the first example below. It is the only route that reaches a screen reader.
|
|
168
|
+
|
|
169
|
+
Dialog mode is unaffected, because the panel is named by `heading` and needs no description at all.
|
|
170
|
+
|
|
171
|
+
#### A tooltip panel on an icon trigger
|
|
172
|
+
|
|
173
|
+
`hover` and `focus` together give the panel to both pointer and keyboard users. Nothing is toggled, so there is no `expanded`, and the name carries the content because a description cannot reach the button inside the trigger.
|
|
174
|
+
|
|
175
|
+
```js
|
|
176
|
+
// main.js
|
|
177
|
+
import '@justeattakeaway/pie-webc/components/tooltip.js';
|
|
178
|
+
import '@justeattakeaway/pie-webc/components/icon-button.js';
|
|
179
|
+
import '@justeattakeaway/pie-icons-webc/dist/IconInfoCircle.js';
|
|
180
|
+
|
|
181
|
+
const trigger = document.querySelector('#delivery-info');
|
|
182
|
+
const panel = document.querySelector('#delivery-panel');
|
|
183
|
+
|
|
184
|
+
trigger.aria = { label: 'Delivery times: orders placed before 6pm arrive today' };
|
|
185
|
+
panel.triggers = ['hover', 'focus'];
|
|
186
|
+
|
|
187
|
+
panel.addEventListener('pie-tooltip-open', () => { panel.isOpen = true; });
|
|
188
|
+
panel.addEventListener('pie-tooltip-close', () => { panel.isOpen = false; });
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
```html
|
|
192
|
+
<script type="module" src="/main.js"></script>
|
|
193
|
+
|
|
194
|
+
<pie-icon-button id="delivery-info" variant="outline">
|
|
195
|
+
<icon-info-circle></icon-info-circle>
|
|
196
|
+
</pie-icon-button>
|
|
197
|
+
|
|
198
|
+
<pie-tooltip id="delivery-panel" trigger="delivery-info" type="icon">
|
|
199
|
+
<span slot="content">Orders placed before 6pm arrive today.</span>
|
|
200
|
+
</pie-tooltip>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
The two handlers are the whole contract. Without them the panel never opens, because the component only ever asks.
|
|
204
|
+
|
|
205
|
+
#### A dialog panel toggled from the trigger
|
|
206
|
+
|
|
207
|
+
Filling the `action` slot makes the panel a dialog, so the trigger gets `haspopup` and, because a click toggles it, `expanded`. Both track the same state you already own.
|
|
208
|
+
|
|
209
|
+
```jsx
|
|
210
|
+
import { useRef, useState } from 'react';
|
|
211
|
+
import { PieButton } from '@justeattakeaway/pie-webc/react/button.js';
|
|
212
|
+
import { PieIconButton } from '@justeattakeaway/pie-webc/react/icon-button.js';
|
|
213
|
+
import { PieTooltip } from '@justeattakeaway/pie-webc/react/tooltip.js';
|
|
214
|
+
import { IconInfoCircle } from '@justeattakeaway/pie-icons-webc/dist/react/IconInfoCircle.js';
|
|
215
|
+
|
|
216
|
+
export function DeliveryTimes () {
|
|
217
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
218
|
+
const triggerRef = useRef(null);
|
|
219
|
+
const actionRef = useRef(null);
|
|
220
|
+
|
|
221
|
+
const open = () => {
|
|
222
|
+
setIsOpen(true);
|
|
223
|
+
// The panel is only focusable once it has rendered and been positioned.
|
|
224
|
+
requestAnimationFrame(() => actionRef.current?.focus({ preventScroll: true }));
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
const close = () => {
|
|
228
|
+
// Only reclaim focus if it is still inside the panel. Closing on a hover-away or a
|
|
229
|
+
// click elsewhere must not yank focus from whatever the user has moved on to.
|
|
230
|
+
const panelHadFocus = document.activeElement?.closest('pie-tooltip');
|
|
231
|
+
|
|
232
|
+
setIsOpen(false);
|
|
233
|
+
|
|
234
|
+
if (panelHadFocus) {
|
|
235
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
return (
|
|
240
|
+
<>
|
|
241
|
+
<PieIconButton
|
|
242
|
+
id="delivery-info"
|
|
243
|
+
ref={triggerRef}
|
|
244
|
+
variant="outline"
|
|
245
|
+
aria={{
|
|
246
|
+
label: 'Delivery times',
|
|
247
|
+
haspopup: 'dialog',
|
|
248
|
+
expanded: isOpen,
|
|
249
|
+
}}>
|
|
250
|
+
<IconInfoCircle />
|
|
251
|
+
</PieIconButton>
|
|
252
|
+
|
|
253
|
+
<PieTooltip
|
|
254
|
+
trigger="delivery-info"
|
|
255
|
+
heading="Delivery times"
|
|
256
|
+
isOpen={isOpen}
|
|
257
|
+
isDismissible
|
|
258
|
+
aria={{ close: 'Close' }}
|
|
259
|
+
triggers={['click']}
|
|
260
|
+
onPieTooltipOpen={open}
|
|
261
|
+
onPieTooltipClose={close}>
|
|
262
|
+
<span slot="content">Orders placed before 6pm arrive today.</span>
|
|
263
|
+
<PieButton slot="action" size="xsmall" ref={actionRef} onClick={close}>
|
|
264
|
+
Got it
|
|
265
|
+
</PieButton>
|
|
266
|
+
</PieTooltip>
|
|
267
|
+
</>
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
`isDismissible` and Escape both route through `onPieTooltipClose`, so a single `close` covers the close button, Escape, a click outside and the action button.
|
|
273
|
+
|
|
274
|
+
The `closest('pie-tooltip')` check works because `document.activeElement` reports the outermost shadow host, so focus on the close button inside the panel's shadow root reads as the `pie-tooltip` element itself. Focus on your slotted action button reports that button, whose `closest` finds the same panel. One check covers both. See [Managing focus](#managing-focus).
|
|
275
|
+
|
|
276
|
+
#### Driving the panel without `triggers`
|
|
277
|
+
|
|
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 emits `pie-tooltip-close`.
|
|
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.
|
|
281
|
+
|
|
282
|
+
```html
|
|
283
|
+
<template>
|
|
284
|
+
<pie-icon-button
|
|
285
|
+
id="delivery-info"
|
|
286
|
+
variant="outline"
|
|
287
|
+
:aria="{ label: 'Delivery times' }">
|
|
288
|
+
<icon-info-circle />
|
|
289
|
+
</pie-icon-button>
|
|
290
|
+
|
|
291
|
+
<pie-tooltip
|
|
292
|
+
trigger="delivery-info"
|
|
293
|
+
heading="Delivery times"
|
|
294
|
+
:isOpen="isOpen"
|
|
295
|
+
isDismissible
|
|
296
|
+
:aria="{ close: 'Close' }"
|
|
297
|
+
@pie-tooltip-close="isOpen = false">
|
|
298
|
+
<span slot="content">Orders placed before 6pm arrive today.</span>
|
|
299
|
+
</pie-tooltip>
|
|
300
|
+
</template>
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Managing focus
|
|
304
|
+
|
|
305
|
+
In tooltip mode there is nothing to do. A tooltip must not take focus, and the close button that `isDismissible` renders is reachable by tabbing.
|
|
306
|
+
|
|
307
|
+
In dialog mode you own two moments:
|
|
308
|
+
|
|
309
|
+
- **On open, move focus into the panel.** Wait for the panel to render and be positioned first, because a `visibility: hidden` element cannot take focus. `await panel.updateComplete` followed by one animation frame is enough.
|
|
310
|
+
- **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.
|
|
51
311
|
|
|
52
312
|
## Usage Examples
|
|
53
313
|
|
|
@@ -56,6 +316,10 @@ Ideally, you should install the component using the **`@justeattakeaway/pie-webc
|
|
|
56
316
|
```js
|
|
57
317
|
// import as module into a js file e.g. main.js
|
|
58
318
|
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' };
|
|
59
323
|
```
|
|
60
324
|
|
|
61
325
|
```html
|
|
@@ -64,19 +328,84 @@ import '@justeattakeaway/pie-webc/components/tooltip.js'
|
|
|
64
328
|
<script type="module" src="/main.js"></script>
|
|
65
329
|
```
|
|
66
330
|
|
|
331
|
+
```html
|
|
332
|
+
<pie-button id="delivery-info">Delivery times</pie-button>
|
|
333
|
+
|
|
334
|
+
<pie-tooltip id="delivery-panel" trigger="delivery-info" isOpen isDismissible>
|
|
335
|
+
<span slot="content">Orders placed before 6pm arrive today.</span>
|
|
336
|
+
</pie-tooltip>
|
|
337
|
+
```
|
|
338
|
+
|
|
67
339
|
**For Native JS Applications, Vue, Angular, Svelte etc.:**
|
|
68
340
|
|
|
69
341
|
```js
|
|
70
342
|
// Vue templates (using Nuxt 3)
|
|
71
343
|
import '@justeattakeaway/pie-webc/components/tooltip.js'
|
|
344
|
+
```
|
|
72
345
|
|
|
346
|
+
```html
|
|
347
|
+
<template>
|
|
348
|
+
<pie-button id="delivery-info">Delivery times</pie-button>
|
|
349
|
+
|
|
350
|
+
<pie-tooltip
|
|
351
|
+
trigger="delivery-info"
|
|
352
|
+
:isOpen="isOpen"
|
|
353
|
+
isDismissible
|
|
354
|
+
:aria="{ close: 'Close' }"
|
|
355
|
+
@pie-tooltip-close="isOpen = false">
|
|
356
|
+
<span slot="content">Orders placed before 6pm arrive today.</span>
|
|
357
|
+
</pie-tooltip>
|
|
358
|
+
</template>
|
|
73
359
|
```
|
|
74
360
|
|
|
75
361
|
**For React Applications:**
|
|
76
362
|
|
|
77
363
|
```jsx
|
|
364
|
+
import { useState } from 'react';
|
|
365
|
+
import { PieButton } from '@justeattakeaway/pie-webc/react/button.js';
|
|
78
366
|
import { PieTooltip } from '@justeattakeaway/pie-webc/react/tooltip.js';
|
|
79
367
|
|
|
368
|
+
export function DeliveryTimes () {
|
|
369
|
+
const [isOpen, setIsOpen] = useState(true);
|
|
370
|
+
|
|
371
|
+
return (
|
|
372
|
+
<>
|
|
373
|
+
<PieButton id="delivery-info">Delivery times</PieButton>
|
|
374
|
+
|
|
375
|
+
<PieTooltip
|
|
376
|
+
trigger="delivery-info"
|
|
377
|
+
isOpen={isOpen}
|
|
378
|
+
isDismissible
|
|
379
|
+
aria={{ close: 'Close' }}
|
|
380
|
+
onPieTooltipClose={() => setIsOpen(false)}>
|
|
381
|
+
<span slot="content">Orders placed before 6pm arrive today.</span>
|
|
382
|
+
</PieTooltip>
|
|
383
|
+
</>
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
**A dialog panel:**
|
|
389
|
+
|
|
390
|
+
Filling the `action` slot switches the panel to a non-modal dialog, which then needs an accessible name.
|
|
391
|
+
|
|
392
|
+
```js
|
|
393
|
+
document.querySelector('#delivery-info').aria = {
|
|
394
|
+
label: 'Delivery times',
|
|
395
|
+
haspopup: 'dialog',
|
|
396
|
+
expanded: true,
|
|
397
|
+
};
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
```html
|
|
401
|
+
<pie-icon-button id="delivery-info" variant="outline">
|
|
402
|
+
<icon-info-circle></icon-info-circle>
|
|
403
|
+
</pie-icon-button>
|
|
404
|
+
|
|
405
|
+
<pie-tooltip trigger="delivery-info" isOpen heading="Delivery times">
|
|
406
|
+
<span slot="content">Orders placed before 6pm arrive today.</span>
|
|
407
|
+
<pie-button slot="action" size="xsmall">Next</pie-button>
|
|
408
|
+
</pie-tooltip>
|
|
80
409
|
```
|
|
81
410
|
|
|
82
411
|
## Questions and Support
|