@justeattakeaway/pie-tooltip 0.4.0 → 0.5.1

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 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)
@@ -51,12 +52,18 @@ Ideally, you should install the component using the **`@justeattakeaway/pie-webc
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 when a configured trigger asks to dismiss the panel. Set `isOpen` to `false` in response. Bubbles and is composed. |
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` element will place the tooltip near to the trigger based on which value is provided.
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
 
@@ -126,25 +133,26 @@ The available space is the viewport, narrowed by any ancestor that clips the pan
126
133
 
127
134
  The panel presents as one of two patterns, inferred from the `action` slot contents. They carry different obligations.
128
135
 
129
- | | `action` slot empty | `action` slot filled |
136
+ | | `action` slot empty and not dismissible | `action` slot filled or `isDismissible` |
130
137
  |---|---|---|
131
138
  | Panel role | `tooltip` | `dialog` |
132
139
  | Contains focusable content | No | Yes |
133
140
  | Accessible name on panel | None | Required, from `heading` or `aria.label` |
134
141
  | In the accessibility tree while closed | Yes, as the trigger's description | No |
135
142
 
136
- A close button does not make the panel a dialog. Only the `action` slot does.
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.
137
144
 
138
145
  ### What the component does
139
146
 
140
- - Sets `role="tooltip"` or `role="dialog"` from the `action` slot, resolved on the client before the first paint.
147
+ - Sets `role="tooltip"` or `role="dialog"` from the `action` slot and `isDismissible`, resolved on the client before the first paint.
141
148
  - Names the dialog panel from `heading`, falling back to `aria.label`.
142
- - 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.
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.
143
151
  - Names the close button from `aria.close` and places it in the tab sequence inside the panel.
144
152
  - Keeps the panel clear of the trigger at every placement, so the panel cannot obscure a focused trigger (WCAG 2.4.11).
145
153
  - Wraps content.
146
154
 
147
- 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).
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).
148
156
 
149
157
  ### What you need to do
150
158
 
@@ -154,8 +162,9 @@ It does not touch the trigger, and it does not move focus. The component never w
154
162
  - **Use a natively interactive element as the trigger**, a button or a link, so focus and click behave correctly.
155
163
  - **Own `isOpen`.** Listen for `pie-tooltip-close` and set `isOpen` to `false` in response.
156
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).
157
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.
158
- - **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.
159
168
  - **Provide a translated `aria.close`** whenever `isDismissible` is set.
160
169
  - **Keep tooltip-mode content short and supplementary.** Anything essential or interactive belongs in dialog mode, or inline in the page.
161
170
 
@@ -163,25 +172,50 @@ It does not touch the trigger, and it does not move focus. The component never w
163
172
 
164
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.
165
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
+
166
177
  | ARIA | Set it when | Value |
167
178
  |---|---|---|
168
179
  | `haspopup` | Dialog mode, so the trigger announces that it opens a dialog | `dialog` |
169
180
  | `expanded` | You toggle the panel from the trigger with a click or a tap | Your `isOpen` value |
170
- | `describedby` | Tooltip mode, and the trigger is a plain HTML element | The `id` of the element you put in the `content` slot |
181
+ | `describedby` | Tooltip mode, and the trigger is a plain HTML element | The `id` of the `pie-tooltip` element itself |
171
182
 
172
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.
173
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
+
174
197
  #### A description cannot cross a shadow boundary
175
198
 
176
- `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.
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.
177
200
 
178
- 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.
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:
179
202
 
180
- Dialog mode is unaffected, because the panel is named by `heading` and needs no description at all.
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.
181
215
 
182
216
  #### A tooltip panel on an icon trigger
183
217
 
184
- `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.
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)).
185
219
 
186
220
  ```js
187
221
  // main.js
@@ -192,7 +226,10 @@ import '@justeattakeaway/pie-icons-webc/dist/IconInfoCircle.js';
192
226
  const trigger = document.querySelector('#delivery-info');
193
227
  const panel = document.querySelector('#delivery-panel');
194
228
 
195
- trigger.aria = { label: 'Delivery times: orders placed before 6pm arrive today' };
229
+ trigger.aria = {
230
+ label: 'Delivery times',
231
+ description: 'Orders placed before 6pm arrive today.',
232
+ };
196
233
  panel.triggers = ['hover', 'focus'];
197
234
 
198
235
  panel.addEventListener('pie-tooltip-open', () => { panel.isOpen = true; });
@@ -227,12 +264,13 @@ import { IconInfoCircle } from '@justeattakeaway/pie-icons-webc/dist/react/IconI
227
264
  export function DeliveryTimes () {
228
265
  const [isOpen, setIsOpen] = useState(false);
229
266
  const triggerRef = useRef(null);
230
- const actionRef = useRef(null);
267
+ const tooltipRef = useRef(null);
231
268
 
232
269
  const open = () => {
233
270
  setIsOpen(true);
234
- // The panel is only focusable once it has rendered and been positioned.
235
- requestAnimationFrame(() => actionRef.current?.focus({ preventScroll: true }));
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();
236
274
  };
237
275
 
238
276
  const close = () => {
@@ -262,6 +300,7 @@ export function DeliveryTimes () {
262
300
  </PieIconButton>
263
301
 
264
302
  <PieTooltip
303
+ ref={tooltipRef}
265
304
  trigger="delivery-info"
266
305
  heading="Delivery times"
267
306
  isOpen={isOpen}
@@ -271,7 +310,7 @@ export function DeliveryTimes () {
271
310
  onPieTooltipOpen={open}
272
311
  onPieTooltipClose={close}>
273
312
  <span slot="content">Orders placed before 6pm arrive today.</span>
274
- <PieButton slot="action" size="xsmall" ref={actionRef} onClick={close}>
313
+ <PieButton slot="action" size="xsmall" onClick={close}>
275
314
  Got it
276
315
  </PieButton>
277
316
  </PieTooltip>
@@ -286,9 +325,7 @@ The `closest('pie-tooltip')` check works because `document.activeElement` report
286
325
 
287
326
  #### Driving the panel without `triggers`
288
327
 
289
- 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`.
290
-
291
- 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`.
292
329
 
293
330
  ```html
294
331
  <template>
@@ -313,24 +350,27 @@ Escape is watched only while at least one trigger is configured, so a panel driv
313
350
 
314
351
  ### Managing focus
315
352
 
316
- 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.
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.
317
354
 
318
355
  In dialog mode you own two moments:
319
356
 
320
- - **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.
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
+
321
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.
322
362
 
323
363
  ## Usage Examples
324
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
+
325
367
  **For HTML:**
326
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
+
327
371
  ```js
328
372
  // import as module into a js file e.g. main.js
329
373
  import '@justeattakeaway/pie-webc/components/tooltip.js'
330
- import '@justeattakeaway/pie-webc/components/button.js'
331
-
332
- // `aria` takes an object, so it is set as a property rather than an attribute.
333
- document.querySelector('#delivery-panel').aria = { close: 'Close' };
334
374
  ```
335
375
 
336
376
  ```html
@@ -340,13 +380,15 @@ document.querySelector('#delivery-panel').aria = { close: 'Close' };
340
380
  ```
341
381
 
342
382
  ```html
343
- <pie-button id="delivery-info">Delivery times</pie-button>
383
+ <button id="delivery-info" aria-describedby="delivery-panel">Delivery times</button>
344
384
 
345
385
  <pie-tooltip id="delivery-panel" trigger="delivery-info" isOpen isDismissible>
346
386
  <span slot="content">Orders placed before 6pm arrive today.</span>
347
387
  </pie-tooltip>
348
388
  ```
349
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
+
350
392
  **For Native JS Applications, Vue, Angular, Svelte etc.:**
351
393
 
352
394
  ```js
@@ -356,9 +398,14 @@ import '@justeattakeaway/pie-webc/components/tooltip.js'
356
398
 
357
399
  ```html
358
400
  <template>
359
- <pie-button id="delivery-info">Delivery times</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>
360
406
 
361
407
  <pie-tooltip
408
+ id="delivery-panel"
362
409
  trigger="delivery-info"
363
410
  :isOpen="isOpen"
364
411
  isDismissible
@@ -369,6 +416,8 @@ import '@justeattakeaway/pie-webc/components/tooltip.js'
369
416
  </template>
370
417
  ```
371
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
+
372
421
  **For React Applications:**
373
422
 
374
423
  ```jsx
@@ -381,9 +430,15 @@ export function DeliveryTimes () {
381
430
 
382
431
  return (
383
432
  <>
384
- <PieButton id="delivery-info">Delivery times</PieButton>
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>
385
439
 
386
440
  <PieTooltip
441
+ id="delivery-panel"
387
442
  trigger="delivery-info"
388
443
  isOpen={isOpen}
389
444
  isDismissible
@@ -413,7 +468,7 @@ document.querySelector('#delivery-info').aria = {
413
468
  <icon-info-circle></icon-info-circle>
414
469
  </pie-icon-button>
415
470
 
416
- <pie-tooltip trigger="delivery-info" isOpen heading="Delivery times">
471
+ <pie-tooltip id="delivery-panel" trigger="delivery-info" isOpen heading="Delivery times">
417
472
  <span slot="content">Orders placed before 6pm arrive today.</span>
418
473
  <pie-button slot="action" size="xsmall">Next</pie-button>
419
474
  </pie-tooltip>
@@ -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. Inferred from the `action` slot rather than\nconfigured: an empty `action` slot is a tooltip, a filled one is a non-modal dialog."
70
+ "description": "The two patterns the panel can present as, inferred from the `action` slot."
71
71
  },
72
72
  {
73
73
  "kind": "variable",
@@ -454,6 +454,21 @@
454
454
  "privacy": "private",
455
455
  "default": "false"
456
456
  },
457
+ {
458
+ "kind": "field",
459
+ "name": "_instanceId",
460
+ "privacy": "private",
461
+ "readonly": true
462
+ },
463
+ {
464
+ "kind": "field",
465
+ "name": "_headingId",
466
+ "type": {
467
+ "text": "string"
468
+ },
469
+ "privacy": "private",
470
+ "readonly": true
471
+ },
457
472
  {
458
473
  "kind": "field",
459
474
  "name": "_mode",
@@ -463,6 +478,16 @@
463
478
  "privacy": "private",
464
479
  "readonly": true
465
480
  },
481
+ {
482
+ "kind": "method",
483
+ "name": "focusPanel",
484
+ "privacy": "public",
485
+ "return": {
486
+ "type": {
487
+ "text": "Promise<boolean>"
488
+ }
489
+ }
490
+ },
466
491
  {
467
492
  "kind": "method",
468
493
  "name": "startTrackingTrigger",
@@ -706,7 +731,7 @@
706
731
  "type": {
707
732
  "text": "Event"
708
733
  },
709
- "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.",
710
735
  "name": "pie-tooltip-close"
711
736
  }
712
737
  ],
package/dist/index.d.ts CHANGED
@@ -5,13 +5,9 @@ import { PropertyValues } from 'lit';
5
5
  import { TemplateResult } from 'lit';
6
6
 
7
7
  declare type AriaProps = {
8
- /**
9
- * The accessible name for the close button. Required whenever `isDismissible` is set.
10
- */
8
+ /** The accessible name for the close button. Required whenever `isDismissible` is set. */
11
9
  close?: string;
12
- /**
13
- * The accessible name for the panel in dialog mode. Only used when `heading` is not provided.
14
- */
10
+ /** The accessible name for the panel in dialog mode, when no `heading` is provided. */
15
11
  label?: string;
16
12
  };
17
13
 
@@ -25,10 +21,7 @@ export declare const defaultProps: DefaultProps;
25
21
 
26
22
  export declare const headingLevels: readonly ["h2", "h3", "h4", "h5", "h6"];
27
23
 
28
- /**
29
- * The two patterns the panel can present as. Inferred from the `action` slot rather than
30
- * configured: an empty `action` slot is a tooltip, a filled one is a non-modal dialog.
31
- */
24
+ /** The two patterns the panel can present as, inferred from the `action` slot. */
32
25
  export declare const modes: readonly ["tooltip", "dialog"];
33
26
 
34
27
  export declare const ON_TOOLTIP_CLOSE_EVENT = "pie-tooltip-close";
@@ -38,7 +31,7 @@ export declare const ON_TOOLTIP_OPEN_EVENT = "pie-tooltip-open";
38
31
  /**
39
32
  * @tagname pie-tooltip
40
33
  * @event {Event} pie-tooltip-open - When a configured trigger asks for the panel. Set `isOpen` to `true` in response.
41
- * @event {Event} pie-tooltip-close - When the close button is clicked, or a configured trigger asks to dismiss the panel. Set `isOpen` to `false` in response.
34
+ * @event {Event} pie-tooltip-close - When the close button is clicked, Escape is pressed, or a configured trigger asks to dismiss the panel. Set `isOpen` to `false` in response.
42
35
  * @slot content - The descriptive content of the panel. Must not contain focusable elements.
43
36
  * @slot action - An optional slot for interactive content such as a `pie-button`. Filling this slot switches the panel to a non-modal dialog.
44
37
  */
@@ -72,11 +65,14 @@ export declare class PieTooltip extends PieElement implements TooltipProps {
72
65
  private _reanchorFrame;
73
66
  private _hoverCloseTimer;
74
67
  private _openedByClick;
68
+ private readonly _instanceId;
69
+ private get _headingId();
75
70
  static styles: CSSResult;
76
71
  private get _mode();
77
72
  protected firstUpdated(): void;
78
73
  protected updated(changedProperties: PropertyValues<this>): void;
79
74
  disconnectedCallback(): void;
75
+ focusPanel(): Promise<boolean>;
80
76
  private startTrackingTrigger;
81
77
  private stopTrackingTrigger;
82
78
  private resolveMode;
@@ -107,63 +103,27 @@ export declare const sizes: readonly ["default", "fit-to-content", "fill-contain
107
103
  export declare type TooltipMode = typeof modes[number];
108
104
 
109
105
  export declare interface TooltipProps {
110
- /**
111
- * The `id` of the element the panel is anchored to. The trigger lives elsewhere in the
112
- * DOM and is never slotted into the tooltip.
113
- */
106
+ /** The `id` of the element the panel is anchored to. */
114
107
  trigger?: string;
115
- /**
116
- * When true, the panel is visible. The component never writes to this property: the
117
- * consumer owns it and updates it in response to the close event.
118
- */
108
+ /** When true, the panel is visible. The component never writes to this property. */
119
109
  isOpen?: boolean;
120
- /**
121
- * The preferred side of the trigger the panel sits on, and its alignment along the cross axis.
122
- * The component repositions the panel automatically — flipping to the opposite side and/or
123
- * shifting its alignment — when the preferred position would collide with the viewport or with
124
- * a clipping scroll container. This behaviour cannot be disabled.
125
- */
110
+ /** The preferred side and alignment; the panel repositions itself to avoid collisions. */
126
111
  position?: typeof positions[number];
127
- /**
128
- * How the panel sizes itself. `default` is a fixed 280px and wraps, `fit-to-content` is as
129
- * wide as its content, and `fill-container` matches the inline size of the trigger's parent
130
- * element. Not applied when `type` is `icon`.
131
- */
112
+ /** How the panel sizes itself. Not applied when `type` is `icon`. */
132
113
  size?: typeof sizes[number];
133
- /**
134
- * The colour treatment of the panel. `default` is the dark panel, `inverse` the light one.
135
- */
114
+ /** The colour treatment of the panel. `default` is the dark panel, `inverse` the light one. */
136
115
  variant?: typeof variants[number];
137
- /**
138
- * The presentation of the panel. `icon` is the compact treatment intended for icon triggers:
139
- * it has no arrow and is always as wide as its content, so `size` and `--tooltip-width` have
140
- * no effect on it.
141
- */
116
+ /** The presentation of the panel. `icon` is the compact, arrow-less treatment. */
142
117
  type?: typeof types[number];
143
- /**
144
- * When true, a close button is rendered inside the panel.
145
- */
118
+ /** 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. */
146
119
  isDismissible?: boolean;
147
- /**
148
- * The text to display in the panel's heading. In dialog mode this also provides the
149
- * panel's accessible name.
150
- */
120
+ /** The text to display in the panel's heading. In dialog mode this also names the panel. */
151
121
  heading?: string;
152
- /**
153
- * The HTML heading tag to use for the panel's heading. Can be h2-h6.
154
- */
122
+ /** The HTML heading tag to use for the panel's heading. Can be h2-h6. */
155
123
  headingLevel?: typeof headingLevels[number];
156
- /**
157
- * The ARIA labels used for various parts of the tooltip.
158
- */
124
+ /** The ARIA labels used for various parts of the tooltip. */
159
125
  aria?: AriaProps;
160
- /**
161
- * Which interactions request that the panel opens and closes. The component never opens or
162
- * closes itself: a configured interaction emits `pie-tooltip-open` or `pie-tooltip-close`
163
- * and the consumer decides whether to honour it by setting `isOpen`. Empty by default, so
164
- * no interaction is watched at all. Configure `hover` and `focus` together for keyboard
165
- * reachability, and `click` for pointer users.
166
- */
126
+ /** Which interactions request that the panel opens and closes. */
167
127
  triggers?: Array<TooltipTrigger>;
168
128
  }
169
129