@vaadin/popover 25.0.0-alpha7 → 25.0.0-alpha9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/popover",
3
- "version": "25.0.0-alpha7",
3
+ "version": "25.0.0-alpha9",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -23,6 +23,8 @@
23
23
  "lit.d.ts",
24
24
  "lit.js",
25
25
  "src",
26
+ "!src/styles/*-base-styles.d.ts",
27
+ "!src/styles/*-base-styles.js",
26
28
  "theme",
27
29
  "vaadin-*.d.ts",
28
30
  "vaadin-*.js",
@@ -37,17 +39,17 @@
37
39
  ],
38
40
  "dependencies": {
39
41
  "@open-wc/dedupe-mixin": "^1.3.0",
40
- "@vaadin/a11y-base": "25.0.0-alpha7",
41
- "@vaadin/component-base": "25.0.0-alpha7",
42
- "@vaadin/lit-renderer": "25.0.0-alpha7",
43
- "@vaadin/overlay": "25.0.0-alpha7",
44
- "@vaadin/vaadin-lumo-styles": "25.0.0-alpha7",
45
- "@vaadin/vaadin-themable-mixin": "25.0.0-alpha7",
42
+ "@vaadin/a11y-base": "25.0.0-alpha9",
43
+ "@vaadin/component-base": "25.0.0-alpha9",
44
+ "@vaadin/lit-renderer": "25.0.0-alpha9",
45
+ "@vaadin/overlay": "25.0.0-alpha9",
46
+ "@vaadin/vaadin-lumo-styles": "25.0.0-alpha9",
47
+ "@vaadin/vaadin-themable-mixin": "25.0.0-alpha9",
46
48
  "lit": "^3.0.0"
47
49
  },
48
50
  "devDependencies": {
49
- "@vaadin/chai-plugins": "25.0.0-alpha7",
50
- "@vaadin/test-runner-commands": "25.0.0-alpha7",
51
+ "@vaadin/chai-plugins": "25.0.0-alpha9",
52
+ "@vaadin/test-runner-commands": "25.0.0-alpha9",
51
53
  "@vaadin/testing-helpers": "^2.0.0",
52
54
  "sinon": "^18.0.0"
53
55
  },
@@ -55,5 +57,5 @@
55
57
  "web-types.json",
56
58
  "web-types.lit.json"
57
59
  ],
58
- "gitHead": "87f72707ce6866892f8be5782fa0da008e87dcbc"
60
+ "gitHead": "bbe4720721e0955ffc87a79b412bee38b1f0eb1e"
59
61
  }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2024 - 2025 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import type { CSSResult } from 'lit';
7
+
8
+ export const popoverOverlayStyles: CSSResult;
@@ -0,0 +1,210 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2024 - 2025 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { css } from 'lit';
7
+ import { overlayStyles } from '@vaadin/overlay/src/styles/vaadin-overlay-base-styles.js';
8
+
9
+ const popoverOverlay = css`
10
+ :host {
11
+ --_arrow-size: var(--vaadin-popover-arrow-size, 8px);
12
+ --_default-offset: 4px;
13
+ --_rtl-multiplier: 1;
14
+ --_border-width: var(--vaadin-popover-border-width, var(--vaadin-overlay-border-width, 1px));
15
+ }
16
+
17
+ [part='overlay']:focus-visible {
18
+ outline: var(--vaadin-focus-ring-width) solid var(--vaadin-focus-ring-color);
19
+ }
20
+
21
+ :host([dir='rtl']) {
22
+ --_rtl-multiplier: -1;
23
+ }
24
+
25
+ :host([modeless][with-backdrop]) [part='backdrop'] {
26
+ pointer-events: none;
27
+ }
28
+
29
+ :host([position^='top'][top-aligned]) [part='overlay'],
30
+ :host([position^='bottom'][top-aligned]) [part='overlay'] {
31
+ margin-top: var(--vaadin-popover-offset-top, var(--_default-offset));
32
+ }
33
+
34
+ [part='overlay'] {
35
+ position: relative;
36
+ overflow: visible;
37
+ max-height: 100%;
38
+ border: var(--_border-width) solid
39
+ var(--vaadin-popover-border-color, var(--vaadin-overlay-border-color, var(--vaadin-border-color)));
40
+ background: var(--vaadin-popover-background, var(--vaadin-overlay-background, var(--vaadin-background-color)));
41
+ box-shadow: var(--vaadin-popover-box-shadow, var(--vaadin-overlay-box-shadow, 0 8px 24px -4px rgba(0, 0, 0, 0.3)));
42
+ }
43
+
44
+ [part='content'] {
45
+ overflow: auto;
46
+ overscroll-behavior: contain;
47
+ box-sizing: border-box;
48
+ max-height: 100%;
49
+ padding: var(--vaadin-popover-padding, var(--vaadin-padding));
50
+ }
51
+
52
+ :host([theme~='no-padding']) [part='content'] {
53
+ padding: 0 !important;
54
+ }
55
+
56
+ /* Increase the area of the popover so the pointer can go from the target directly to it. */
57
+ [part='overlay']::before {
58
+ position: absolute;
59
+ content: '';
60
+ inset-block: calc(var(--vaadin-popover-offset-top, var(--_default-offset)) * -1)
61
+ calc(var(--vaadin-popover-offset-bottom, var(--_default-offset)) * -1);
62
+ inset-inline: calc(var(--vaadin-popover-offset-start, var(--_default-offset)) * -1)
63
+ calc(var(--vaadin-popover-offset-end, var(--_default-offset)) * -1);
64
+ z-index: -1;
65
+ pointer-events: auto;
66
+ }
67
+
68
+ :host([position^='top'][bottom-aligned]) [part='overlay'],
69
+ :host([position^='bottom'][bottom-aligned]) [part='overlay'] {
70
+ margin-bottom: var(--vaadin-popover-offset-bottom, var(--_default-offset));
71
+ }
72
+
73
+ :host([position^='start'][start-aligned]) [part='overlay'],
74
+ :host([position^='end'][start-aligned]) [part='overlay'] {
75
+ margin-inline-start: var(--vaadin-popover-offset-start, var(--_default-offset));
76
+ }
77
+
78
+ :host([position^='start'][end-aligned]) [part='overlay'],
79
+ :host([position^='end'][end-aligned]) [part='overlay'] {
80
+ margin-inline-end: var(--vaadin-popover-offset-end, var(--_default-offset));
81
+ }
82
+
83
+ [part='arrow'] {
84
+ display: none;
85
+ }
86
+
87
+ :host([theme~='arrow']) {
88
+ --_default-offset: calc(4px + var(--_arrow-size) / 2);
89
+ }
90
+
91
+ :host([theme~='arrow']) [part='arrow'] {
92
+ display: block;
93
+ position: absolute;
94
+ background: inherit;
95
+ border: inherit;
96
+ border-start-start-radius: var(--vaadin-popover-arrow-border-radius, 0);
97
+ outline: inherit;
98
+ box-shadow: inherit;
99
+ width: var(--_arrow-size);
100
+ height: var(--_arrow-size);
101
+ rotate: 45deg;
102
+ --o: 20px; /* clip-path outset, how far outward it extends to reveal the outline and box shadow */
103
+ --b: var(--_border-width);
104
+ /* We need this elaborate clip-path to allow the arrow bg and border to cover
105
+ the overlay border but prevent the outline and box-shadow from covering it */
106
+ clip-path: polygon(
107
+ calc(var(--o) * -1) calc(var(--o) * -1),
108
+ calc(100% + var(--o) - var(--b)) calc(var(--o) * -1),
109
+ calc(100% - var(--b) * 1.4) 0,
110
+ 100% 0,
111
+ calc(100% - var(--b)) var(--b),
112
+ calc(100% - var(--b)) calc(var(--b) + var(--ff, 0px)),
113
+ calc(var(--b) + var(--ff, 0px)) calc(100% - var(--b)),
114
+ calc(var(--b)) calc(100% - var(--b)),
115
+ 0 100%,
116
+ 0 calc(100% - var(--b) * 1.4),
117
+ calc(var(--o) * -1) calc(100% + var(--o) - var(--b))
118
+ );
119
+ }
120
+
121
+ /* Firefox renders a blurry edge for a diagonal clip-path + rotation,
122
+ so we need to extend the clip-path slightly further on the diagonal */
123
+ @supports (-moz-appearance: none) {
124
+ :host([theme~='arrow']) [part='arrow'] {
125
+ --ff: 1px;
126
+ }
127
+ }
128
+
129
+ /* bottom / top */
130
+ :host([theme~='arrow']:is([position^='bottom'], [position^='top'])[start-aligned]) [part='arrow'] {
131
+ inset-inline-start: calc(var(--_arrow-size) * 2);
132
+ }
133
+
134
+ :host([theme~='arrow']:is([position^='bottom'], [position^='top'])[end-aligned]) [part='arrow'] {
135
+ inset-inline-end: calc(var(--_arrow-size) * 2);
136
+ }
137
+
138
+ :host([theme~='arrow']:is([position^='bottom'], [position^='top'])[arrow-centered]) [part='arrow'] {
139
+ inset-inline-start: 50%;
140
+ }
141
+
142
+ /* bottom */
143
+ :host([theme~='arrow']:is([position^='bottom'], [position^='top'])[top-aligned]) [part='arrow'] {
144
+ top: 0;
145
+ translate: calc(-50% * var(--_rtl-multiplier)) -50%;
146
+ }
147
+
148
+ :host([theme~='arrow']:is([position^='bottom'], [position^='top'])[end-aligned][top-aligned]) [part='arrow'] {
149
+ translate: calc(50% * var(--_rtl-multiplier)) -50%;
150
+ }
151
+
152
+ /* top */
153
+ :host([theme~='arrow']:is([position^='bottom'], [position^='top'])[bottom-aligned]) [part='arrow'] {
154
+ bottom: 0;
155
+ rotate: 225deg;
156
+ translate: calc(-50% * var(--_rtl-multiplier)) 50%;
157
+ }
158
+
159
+ :host([theme~='arrow']:is([position^='bottom'], [position^='top'])[end-aligned][bottom-aligned]) [part='arrow'] {
160
+ translate: calc(50% * var(--_rtl-multiplier)) 50%;
161
+ }
162
+
163
+ /* start / end */
164
+ :host([theme~='arrow']:is([position^='start'], [position^='end'])[top-aligned]) [part='arrow'] {
165
+ rotate: -45deg;
166
+ top: calc(var(--_arrow-size) * 2);
167
+ }
168
+
169
+ :host([theme~='arrow']:is([position^='start'], [position^='end'])[bottom-aligned]) [part='arrow'] {
170
+ rotate: -45deg;
171
+ bottom: calc(var(--_arrow-size) * 2);
172
+ }
173
+
174
+ :host([theme~='arrow']:is([position='start'], [position='end'])[top-aligned]) [part='arrow'] {
175
+ top: 50%;
176
+ }
177
+
178
+ :host([dir='rtl'][theme~='arrow']:is([position^='start'], [position^='end'])) [part='arrow'] {
179
+ scale: -1;
180
+ }
181
+
182
+ /* end */
183
+ :host([theme~='arrow']:is([position^='start'], [position^='end'])[start-aligned]) [part='arrow'] {
184
+ inset-inline-start: 0;
185
+ translate: calc(-50% * var(--_rtl-multiplier)) -50%;
186
+ }
187
+
188
+ :host([theme~='arrow']:is([position^='start'], [position^='end'])[start-aligned][bottom-aligned]) [part='arrow'] {
189
+ translate: calc(-50% * var(--_rtl-multiplier)) 50%;
190
+ }
191
+
192
+ /* start */
193
+ :host([theme~='arrow']:is([position^='start'], [position^='end'])[end-aligned]) [part='arrow'] {
194
+ rotate: 135deg;
195
+ inset-inline-end: 0;
196
+ translate: calc(50% * var(--_rtl-multiplier)) -50%;
197
+ }
198
+
199
+ :host([theme~='arrow']:is([position^='start'], [position^='end'])[end-aligned][bottom-aligned]) [part='arrow'] {
200
+ translate: calc(50% * var(--_rtl-multiplier)) 50%;
201
+ }
202
+
203
+ @media (forced-colors: active) {
204
+ :host {
205
+ --_border-width: 3px;
206
+ }
207
+ }
208
+ `;
209
+
210
+ export const popoverOverlayStyles = [overlayStyles, popoverOverlay];
@@ -7,13 +7,17 @@ import { css } from 'lit';
7
7
  import { overlayStyles } from '@vaadin/overlay/src/styles/vaadin-overlay-core-styles.js';
8
8
 
9
9
  const popoverOverlay = css`
10
+ :host {
11
+ --_default-offset: 0;
12
+ }
13
+
10
14
  :host([modeless][with-backdrop]) [part='backdrop'] {
11
15
  pointer-events: none;
12
16
  }
13
17
 
14
18
  :host([position^='top'][top-aligned]) [part='overlay'],
15
19
  :host([position^='bottom'][top-aligned]) [part='overlay'] {
16
- margin-top: var(--vaadin-popover-offset-top, 0);
20
+ margin-top: var(--vaadin-popover-offset-top, var(--_default-offset));
17
21
  }
18
22
 
19
23
  [part='overlay'] {
@@ -32,25 +36,27 @@ const popoverOverlay = css`
32
36
  [part='overlay']::before {
33
37
  position: absolute;
34
38
  content: '';
35
- inset-block: calc(var(--vaadin-popover-offset-top, 0) * -1) calc(var(--vaadin-popover-offset-bottom, 0) * -1);
36
- inset-inline: calc(var(--vaadin-popover-offset-start, 0) * -1) calc(var(--vaadin-popover-offset-end, 0) * -1);
39
+ inset-block: calc(var(--vaadin-popover-offset-top, var(--_default-offset)) * -1)
40
+ calc(var(--vaadin-popover-offset-bottom, var(--_default-offset)) * -1);
41
+ inset-inline: calc(var(--vaadin-popover-offset-start, var(--_default-offset)) * -1)
42
+ calc(var(--vaadin-popover-offset-end, var(--_default-offset)) * -1);
37
43
  z-index: -1;
38
44
  pointer-events: auto;
39
45
  }
40
46
 
41
47
  :host([position^='top'][bottom-aligned]) [part='overlay'],
42
48
  :host([position^='bottom'][bottom-aligned]) [part='overlay'] {
43
- margin-bottom: var(--vaadin-popover-offset-bottom, 0);
49
+ margin-bottom: var(--vaadin-popover-offset-bottom, var(--_default-offset));
44
50
  }
45
51
 
46
52
  :host([position^='start'][start-aligned]) [part='overlay'],
47
53
  :host([position^='end'][start-aligned]) [part='overlay'] {
48
- margin-inline-start: var(--vaadin-popover-offset-start, 0);
54
+ margin-inline-start: var(--vaadin-popover-offset-start, var(--_default-offset));
49
55
  }
50
56
 
51
57
  :host([position^='start'][end-aligned]) [part='overlay'],
52
58
  :host([position^='end'][end-aligned]) [part='overlay'] {
53
- margin-inline-end: var(--vaadin-popover-offset-end, 0);
59
+ margin-inline-end: var(--vaadin-popover-offset-end, var(--_default-offset));
54
60
  }
55
61
 
56
62
  [part='arrow'] {
@@ -5,26 +5,6 @@
5
5
  */
6
6
  import { OverlayMixin } from '@vaadin/overlay/src/vaadin-overlay-mixin.js';
7
7
  import { PositionMixin } from '@vaadin/overlay/src/vaadin-overlay-position-mixin.js';
8
- import { setNestedOverlay } from '@vaadin/overlay/src/vaadin-overlay-stack-mixin.js';
9
-
10
- /**
11
- * Returns the closest parent overlay for given node, if any.
12
- * @param {HTMLElement} node
13
- * @return {HTMLElement}
14
- */
15
- const getClosestOverlay = (node) => {
16
- let n = node;
17
-
18
- while (n && n !== node.ownerDocument) {
19
- n = n.parentNode || n.host;
20
-
21
- if (n && n._hasOverlayStackMixin) {
22
- return n;
23
- }
24
- }
25
-
26
- return null;
27
- };
28
8
 
29
9
  /**
30
10
  * A mixin providing common popover overlay functionality.
@@ -44,19 +24,6 @@ export const PopoverOverlayMixin = (superClass) =>
44
24
  };
45
25
  }
46
26
 
47
- static get observers() {
48
- return ['__openedOrTargetChanged(opened, positionTarget)'];
49
- }
50
-
51
- /**
52
- * Tag name prefix used by custom properties.
53
- * @protected
54
- * @return {string}
55
- */
56
- get _tagNamePrefix() {
57
- return 'vaadin-popover';
58
- }
59
-
60
27
  /**
61
28
  * @protected
62
29
  * @override
@@ -68,15 +35,6 @@ export const PopoverOverlayMixin = (superClass) =>
68
35
  return;
69
36
  }
70
37
 
71
- // Copy custom properties from the owner
72
- if (this.owner) {
73
- const style = getComputedStyle(this.owner);
74
- ['top', 'bottom', 'start', 'end'].forEach((prop) => {
75
- const propertyName = `--${this._tagNamePrefix}-offset-${prop}`;
76
- this.style.setProperty(propertyName, style.getPropertyValue(propertyName));
77
- });
78
- }
79
-
80
38
  this.removeAttribute('arrow-centered');
81
39
 
82
40
  // Center the overlay horizontally
@@ -114,14 +72,4 @@ export const PopoverOverlayMixin = (superClass) =>
114
72
  this.style.top = `${overlayRect.top + offset}px`;
115
73
  }
116
74
  }
117
-
118
- /** @private */
119
- __openedOrTargetChanged(opened, target) {
120
- if (target) {
121
- const parent = getClosestOverlay(target);
122
- if (parent) {
123
- setNestedOverlay(parent, opened ? this : null);
124
- }
125
- }
126
- }
127
75
  };
@@ -4,6 +4,7 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { html, LitElement } from 'lit';
7
+ import { isElementFocused } from '@vaadin/a11y-base/src/focus-utils.js';
7
8
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
8
9
  import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
9
10
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
@@ -23,7 +24,7 @@ import { PopoverOverlayMixin } from './vaadin-popover-overlay-mixin.js';
23
24
  * @private
24
25
  */
25
26
  class PopoverOverlay extends PopoverOverlayMixin(
26
- DirMixin(ThemableMixin(LumoInjectionMixin(PolylitMixin(LitElement)))),
27
+ DirMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement)))),
27
28
  ) {
28
29
  static get is() {
29
30
  return 'vaadin-popover-overlay';
@@ -43,6 +44,37 @@ class PopoverOverlay extends PopoverOverlayMixin(
43
44
  </div>
44
45
  `;
45
46
  }
47
+
48
+ /** @protected */
49
+ updated(props) {
50
+ super.updated(props);
51
+
52
+ if (props.has('restoreFocusNode') && this.opened) {
53
+ // Save focus to be restored when target is set while opened
54
+ if (this.restoreFocusNode && isElementFocused(this.restoreFocusNode.focusElement || this.restoreFocusNode)) {
55
+ this.__focusRestorationController.saveFocus();
56
+ } else if (!this.restoreFocusNode) {
57
+ // Do not restore focus when target is cleared while opened
58
+ this.__focusRestorationController.focusNode = null;
59
+ }
60
+ }
61
+ }
62
+
63
+ /**
64
+ * @override
65
+ * @protected
66
+ */
67
+ get _contentRoot() {
68
+ return this.owner;
69
+ }
70
+
71
+ /**
72
+ * @override
73
+ * @protected
74
+ */
75
+ get _modalRoot() {
76
+ return this.owner;
77
+ }
46
78
  }
47
79
 
48
80
  defineCustomElement(PopoverOverlay);
@@ -37,16 +37,13 @@ export type PopoverEventMap = HTMLElementEventMap & PopoverCustomEventMap;
37
37
  *
38
38
  * ### Styling
39
39
  *
40
- * `<vaadin-popover>` uses `<vaadin-popover-overlay>` internal
41
- * themable component as the actual visible overlay.
42
- *
43
- * See [`<vaadin-overlay>`](#/elements/vaadin-overlay) documentation
44
- * for `<vaadin-popover-overlay>` parts.
45
- *
46
- * In addition to `<vaadin-overlay>` parts, the following parts are available for styling:
40
+ * The following shadow DOM parts are available for styling:
47
41
  *
48
42
  * Part name | Description
49
43
  * -----------------|-------------------------------------------
44
+ * `backdrop` | Backdrop of the overlay
45
+ * `overlay` | The overlay container
46
+ * `content` | The overlay content
50
47
  * `arrow` | Optional arrow pointing to the target when using `theme="arrow"`
51
48
  *
52
49
  * The following state attributes are available for styling:
@@ -55,9 +52,6 @@ export type PopoverEventMap = HTMLElementEventMap & PopoverCustomEventMap;
55
52
  * -----------------|----------------------------------------
56
53
  * `position` | Reflects the `position` property value.
57
54
  *
58
- * Note: the `theme` attribute value set on `<vaadin-popover>` is
59
- * propagated to the internal `<vaadin-popover-overlay>` component.
60
- *
61
55
  * ### Custom CSS Properties
62
56
  *
63
57
  * The following custom CSS properties are available on the `<vaadin-popover>` element:
@@ -96,14 +90,14 @@ declare class Popover extends PopoverPositionMixin(
96
90
  static setDefaultHoverDelay(hoverDelay: number): void;
97
91
 
98
92
  /**
99
- * String used to label the overlay to screen reader users.
93
+ * String used to label the popover to screen reader users.
100
94
  *
101
95
  * @attr {string} accessible-name
102
96
  */
103
97
  accessibleName: string | null | undefined;
104
98
 
105
99
  /**
106
- * Id of the element used as label of the overlay to screen reader users.
100
+ * Id of the element used as label of the popover to screen reader users.
107
101
  *
108
102
  * @attr {string} accessible-name-ref
109
103
  */
@@ -169,16 +169,13 @@ const isLastOverlay = (overlay) => {
169
169
  *
170
170
  * ### Styling
171
171
  *
172
- * `<vaadin-popover>` uses `<vaadin-popover-overlay>` internal
173
- * themable component as the actual visible overlay.
174
- *
175
- * See [`<vaadin-overlay>`](#/elements/vaadin-overlay) documentation
176
- * for `<vaadin-popover-overlay>` parts.
177
- *
178
- * In addition to `<vaadin-overlay>` parts, the following parts are available for styling:
172
+ * The following shadow DOM parts are available for styling:
179
173
  *
180
174
  * Part name | Description
181
175
  * -----------------|-------------------------------------------
176
+ * `backdrop` | Backdrop of the overlay
177
+ * `overlay` | The overlay container
178
+ * `content` | The overlay content
182
179
  * `arrow` | Optional arrow pointing to the target when using `theme="arrow"`
183
180
  *
184
181
  * The following state attributes are available for styling:
@@ -187,9 +184,6 @@ const isLastOverlay = (overlay) => {
187
184
  * -----------------|----------------------------------------
188
185
  * `position` | Reflects the `position` property value.
189
186
  *
190
- * Note: the `theme` attribute value set on `<vaadin-popover>` is
191
- * propagated to the internal `<vaadin-popover-overlay>` component.
192
- *
193
187
  * ### Custom CSS Properties
194
188
  *
195
189
  * The following custom CSS properties are available on the `<vaadin-popover>` element:
@@ -224,7 +218,7 @@ class Popover extends PopoverPositionMixin(
224
218
  static get styles() {
225
219
  return css`
226
220
  :host {
227
- display: none !important;
221
+ display: contents;
228
222
  }
229
223
  `;
230
224
  }
@@ -232,7 +226,7 @@ class Popover extends PopoverPositionMixin(
232
226
  static get properties() {
233
227
  return {
234
228
  /**
235
- * String used to label the overlay to screen reader users.
229
+ * String used to label the popover to screen reader users.
236
230
  *
237
231
  * @attr {string} accessible-name
238
232
  */
@@ -241,7 +235,7 @@ class Popover extends PopoverPositionMixin(
241
235
  },
242
236
 
243
237
  /**
244
- * Id of the element used as label of the overlay to screen reader users.
238
+ * Id of the element used as label of the popover to screen reader users.
245
239
  *
246
240
  * @attr {string} accessible-name-ref
247
241
  */
@@ -415,11 +409,6 @@ class Popover extends PopoverPositionMixin(
415
409
  value: false,
416
410
  sync: true,
417
411
  },
418
-
419
- /** @private */
420
- __overlayId: {
421
- type: String,
422
- },
423
412
  };
424
413
  }
425
414
 
@@ -460,7 +449,7 @@ class Popover extends PopoverPositionMixin(
460
449
  constructor() {
461
450
  super();
462
451
 
463
- this.__overlayId = `vaadin-popover-${generateUniqueId()}`;
452
+ this.__generatedId = `vaadin-popover-${generateUniqueId()}`;
464
453
 
465
454
  this.__onGlobalClick = this.__onGlobalClick.bind(this);
466
455
  this.__onGlobalKeyDown = this.__onGlobalKeyDown.bind(this);
@@ -479,10 +468,7 @@ class Popover extends PopoverPositionMixin(
479
468
 
480
469
  return html`
481
470
  <vaadin-popover-overlay
482
- id="${this.__overlayId}"
483
- role="${this.overlayRole}"
484
- aria-label="${ifDefined(this.accessibleName)}"
485
- aria-labelledby="${ifDefined(this.accessibleNameRef)}"
471
+ id="overlay"
486
472
  .renderer="${this.renderer}"
487
473
  .owner="${this}"
488
474
  theme="${ifDefined(this._theme)}"
@@ -504,11 +490,14 @@ class Popover extends PopoverPositionMixin(
504
490
  @opened-changed="${this.__onOpenedChanged}"
505
491
  .restoreFocusOnClose="${this.__shouldRestoreFocus}"
506
492
  .restoreFocusNode="${this.target}"
493
+ exportparts="backdrop, overlay, content, arrow"
507
494
  @vaadin-overlay-escape-press="${this.__onEscapePress}"
508
495
  @vaadin-overlay-outside-click="${this.__onOutsideClick}"
509
496
  @vaadin-overlay-open="${this.__onOverlayOpened}"
510
497
  @vaadin-overlay-closed="${this.__onOverlayClosed}"
511
- ></vaadin-popover-overlay>
498
+ >
499
+ <slot></slot>
500
+ </vaadin-popover-overlay>
512
501
  `;
513
502
  }
514
503
 
@@ -530,13 +519,43 @@ class Popover extends PopoverPositionMixin(
530
519
  ready() {
531
520
  super.ready();
532
521
 
533
- this._overlayElement = this.$[this.__overlayId];
522
+ this._overlayElement = this.$.overlay;
523
+ }
524
+
525
+ /** @protected */
526
+ updated(props) {
527
+ super.updated(props);
528
+
529
+ if (props.has('overlayRole')) {
530
+ this.setAttribute('role', this.overlayRole);
531
+ }
532
+
533
+ if (props.has('accessibleName')) {
534
+ if (this.accessibleName) {
535
+ this.setAttribute('aria-label', this.accessibleName);
536
+ } else {
537
+ this.removeAttribute('aria-label');
538
+ }
539
+ }
540
+
541
+ if (props.has('accessibleNameRef')) {
542
+ if (this.accessibleNameRef) {
543
+ this.setAttribute('aria-labelledby', this.accessibleNameRef);
544
+ } else {
545
+ this.removeAttribute('aria-labelledby');
546
+ }
547
+ }
534
548
  }
535
549
 
536
550
  /** @protected */
537
551
  connectedCallback() {
538
552
  super.connectedCallback();
539
553
 
554
+ // If no user ID is provided, set generated ID
555
+ if (!this.id) {
556
+ this.id = this.__generatedId;
557
+ }
558
+
540
559
  document.documentElement.addEventListener('click', this.__onGlobalClick, true);
541
560
  }
542
561
 
@@ -608,7 +627,7 @@ class Popover extends PopoverPositionMixin(
608
627
  effectiveTarget.setAttribute('aria-expanded', opened ? 'true' : 'false');
609
628
 
610
629
  if (opened) {
611
- effectiveTarget.setAttribute('aria-controls', this.__overlayId);
630
+ effectiveTarget.setAttribute('aria-controls', this.id);
612
631
  } else {
613
632
  effectiveTarget.removeAttribute('aria-controls');
614
633
  }
@@ -787,7 +806,7 @@ class Popover extends PopoverPositionMixin(
787
806
  return;
788
807
  }
789
808
 
790
- if ((this.__hasTrigger('focus') && this.__mouseDownInside) || this._overlayElement.contains(event.relatedTarget)) {
809
+ if ((this.__hasTrigger('focus') && this.__mouseDownInside) || this.contains(event.relatedTarget)) {
791
810
  return;
792
811
  }
793
812
 
@@ -815,7 +834,7 @@ class Popover extends PopoverPositionMixin(
815
834
  return;
816
835
  }
817
836
 
818
- if (this._overlayElement.contains(event.relatedTarget)) {
837
+ if (this.contains(event.relatedTarget)) {
819
838
  return;
820
839
  }
821
840
 
@@ -846,7 +865,8 @@ class Popover extends PopoverPositionMixin(
846
865
  if (
847
866
  (this.__hasTrigger('focus') && this.__mouseDownInside) ||
848
867
  event.relatedTarget === this.target ||
849
- this._overlayElement.contains(event.relatedTarget)
868
+ event.relatedTarget === this._overlayElement ||
869
+ this.contains(event.relatedTarget)
850
870
  ) {
851
871
  return;
852
872
  }
@@ -904,6 +924,11 @@ class Popover extends PopoverPositionMixin(
904
924
  }
905
925
 
906
926
  if (this.__hasTrigger('focus')) {
927
+ // Do not restore focus if closed on focusout on Tab
928
+ if (isKeyboardActive()) {
929
+ this.__shouldRestoreFocus = false;
930
+ }
931
+
907
932
  this._openedStateController.close(true);
908
933
  }
909
934
  }
@@ -7,12 +7,8 @@ import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themab
7
7
 
8
8
  const popoverOverlay = css`
9
9
  :host {
10
- --vaadin-popover-offset-top: var(--_vaadin-popover-default-offset);
11
- --vaadin-popover-offset-bottom: var(--_vaadin-popover-default-offset);
12
- --vaadin-popover-offset-start: var(--_vaadin-popover-default-offset);
13
- --vaadin-popover-offset-end: var(--_vaadin-popover-default-offset);
14
10
  --vaadin-popover-arrow-size: 0.5rem;
15
- --_vaadin-popover-default-offset: var(--lumo-space-xs);
11
+ --_default-offset: var(--lumo-space-xs);
16
12
  }
17
13
 
18
14
  [part='overlay'] {
@@ -24,11 +20,11 @@ const popoverOverlay = css`
24
20
  }
25
21
 
26
22
  :host([theme~='no-padding']) [part='content'] {
27
- padding: 0;
23
+ padding: 0 !important;
28
24
  }
29
25
 
30
26
  :host([theme~='arrow']) {
31
- --_vaadin-popover-default-offset: calc(var(--lumo-space-s) + var(--vaadin-popover-arrow-size) / 2);
27
+ --_default-offset: calc(var(--lumo-space-s) + var(--vaadin-popover-arrow-size) / 2);
32
28
  }
33
29
 
34
30
  /* top / bottom position */
package/web-types.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/popover",
4
- "version": "25.0.0-alpha7",
4
+ "version": "25.0.0-alpha9",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
8
8
  "elements": [
9
9
  {
10
10
  "name": "vaadin-popover",
11
- "description": "`<vaadin-popover>` is a Web Component for creating overlays\nthat are positioned next to specified DOM element (target).\n\nUnlike `<vaadin-tooltip>`, the popover supports rich content\nthat can be provided by using `renderer` function.\n\n### Styling\n\n`<vaadin-popover>` uses `<vaadin-popover-overlay>` internal\nthemable component as the actual visible overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha7/#/elements/vaadin-overlay) documentation\nfor `<vaadin-popover-overlay>` parts.\n\nIn addition to `<vaadin-overlay>` parts, the following parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`arrow` | Optional arrow pointing to the target when using `theme=\"arrow\"`\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|----------------------------------------\n`position` | Reflects the `position` property value.\n\nNote: the `theme` attribute value set on `<vaadin-popover>` is\npropagated to the internal `<vaadin-popover-overlay>` component.\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available on the `<vaadin-popover>` element:\n\nCustom CSS property | Description\n---------------------------------|-------------\n`--vaadin-popover-offset-top` | Used as an offset when the popover is aligned vertically below the target\n`--vaadin-popover-offset-bottom` | Used as an offset when the popover is aligned vertically above the target\n`--vaadin-popover-offset-start` | Used as an offset when the popover is aligned horizontally after the target\n`--vaadin-popover-offset-end` | Used as an offset when the popover is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
11
+ "description": "`<vaadin-popover>` is a Web Component for creating overlays\nthat are positioned next to specified DOM element (target).\n\nUnlike `<vaadin-tooltip>`, the popover supports rich content\nthat can be provided by using `renderer` function.\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n`arrow` | Optional arrow pointing to the target when using `theme=\"arrow\"`\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|----------------------------------------\n`position` | Reflects the `position` property value.\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available on the `<vaadin-popover>` element:\n\nCustom CSS property | Description\n---------------------------------|-------------\n`--vaadin-popover-offset-top` | Used as an offset when the popover is aligned vertically below the target\n`--vaadin-popover-offset-bottom` | Used as an offset when the popover is aligned vertically above the target\n`--vaadin-popover-offset-start` | Used as an offset when the popover is aligned horizontally after the target\n`--vaadin-popover-offset-end` | Used as an offset when the popover is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
12
12
  "attributes": [
13
13
  {
14
14
  "name": "overlay-class",
@@ -45,7 +45,7 @@
45
45
  },
46
46
  {
47
47
  "name": "accessible-name",
48
- "description": "String used to label the overlay to screen reader users.",
48
+ "description": "String used to label the popover to screen reader users.",
49
49
  "value": {
50
50
  "type": [
51
51
  "string",
@@ -56,7 +56,7 @@
56
56
  },
57
57
  {
58
58
  "name": "accessible-name-ref",
59
- "description": "Id of the element used as label of the overlay to screen reader users.",
59
+ "description": "Id of the element used as label of the popover to screen reader users.",
60
60
  "value": {
61
61
  "type": [
62
62
  "string",
@@ -257,7 +257,7 @@
257
257
  },
258
258
  {
259
259
  "name": "accessibleName",
260
- "description": "String used to label the overlay to screen reader users.",
260
+ "description": "String used to label the popover to screen reader users.",
261
261
  "value": {
262
262
  "type": [
263
263
  "string",
@@ -268,7 +268,7 @@
268
268
  },
269
269
  {
270
270
  "name": "accessibleNameRef",
271
- "description": "Id of the element used as label of the overlay to screen reader users.",
271
+ "description": "Id of the element used as label of the popover to screen reader users.",
272
272
  "value": {
273
273
  "type": [
274
274
  "string",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/popover",
4
- "version": "25.0.0-alpha7",
4
+ "version": "25.0.0-alpha9",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -16,7 +16,7 @@
16
16
  "elements": [
17
17
  {
18
18
  "name": "vaadin-popover",
19
- "description": "`<vaadin-popover>` is a Web Component for creating overlays\nthat are positioned next to specified DOM element (target).\n\nUnlike `<vaadin-tooltip>`, the popover supports rich content\nthat can be provided by using `renderer` function.\n\n### Styling\n\n`<vaadin-popover>` uses `<vaadin-popover-overlay>` internal\nthemable component as the actual visible overlay.\n\nSee [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha7/#/elements/vaadin-overlay) documentation\nfor `<vaadin-popover-overlay>` parts.\n\nIn addition to `<vaadin-overlay>` parts, the following parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`arrow` | Optional arrow pointing to the target when using `theme=\"arrow\"`\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|----------------------------------------\n`position` | Reflects the `position` property value.\n\nNote: the `theme` attribute value set on `<vaadin-popover>` is\npropagated to the internal `<vaadin-popover-overlay>` component.\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available on the `<vaadin-popover>` element:\n\nCustom CSS property | Description\n---------------------------------|-------------\n`--vaadin-popover-offset-top` | Used as an offset when the popover is aligned vertically below the target\n`--vaadin-popover-offset-bottom` | Used as an offset when the popover is aligned vertically above the target\n`--vaadin-popover-offset-start` | Used as an offset when the popover is aligned horizontally after the target\n`--vaadin-popover-offset-end` | Used as an offset when the popover is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
19
+ "description": "`<vaadin-popover>` is a Web Component for creating overlays\nthat are positioned next to specified DOM element (target).\n\nUnlike `<vaadin-tooltip>`, the popover supports rich content\nthat can be provided by using `renderer` function.\n\n### Styling\n\nThe following shadow DOM parts are available for styling:\n\nPart name | Description\n-----------------|-------------------------------------------\n`backdrop` | Backdrop of the overlay\n`overlay` | The overlay container\n`content` | The overlay content\n`arrow` | Optional arrow pointing to the target when using `theme=\"arrow\"`\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-----------------|----------------------------------------\n`position` | Reflects the `position` property value.\n\n### Custom CSS Properties\n\nThe following custom CSS properties are available on the `<vaadin-popover>` element:\n\nCustom CSS property | Description\n---------------------------------|-------------\n`--vaadin-popover-offset-top` | Used as an offset when the popover is aligned vertically below the target\n`--vaadin-popover-offset-bottom` | Used as an offset when the popover is aligned vertically above the target\n`--vaadin-popover-offset-start` | Used as an offset when the popover is aligned horizontally after the target\n`--vaadin-popover-offset-end` | Used as an offset when the popover is aligned horizontally before the target\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
20
20
  "extension": true,
21
21
  "attributes": [
22
22
  {
@@ -91,14 +91,14 @@
91
91
  },
92
92
  {
93
93
  "name": ".accessibleName",
94
- "description": "String used to label the overlay to screen reader users.",
94
+ "description": "String used to label the popover to screen reader users.",
95
95
  "value": {
96
96
  "kind": "expression"
97
97
  }
98
98
  },
99
99
  {
100
100
  "name": ".accessibleNameRef",
101
- "description": "Id of the element used as label of the overlay to screen reader users.",
101
+ "description": "Id of the element used as label of the popover to screen reader users.",
102
102
  "value": {
103
103
  "kind": "expression"
104
104
  }