@vaadin/popover 25.0.0-alpha7 → 25.0.0-alpha8

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-alpha8",
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-alpha8",
43
+ "@vaadin/component-base": "25.0.0-alpha8",
44
+ "@vaadin/lit-renderer": "25.0.0-alpha8",
45
+ "@vaadin/overlay": "25.0.0-alpha8",
46
+ "@vaadin/vaadin-lumo-styles": "25.0.0-alpha8",
47
+ "@vaadin/vaadin-themable-mixin": "25.0.0-alpha8",
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-alpha8",
52
+ "@vaadin/test-runner-commands": "25.0.0-alpha8",
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": "ebf53673d5f639d2b1b6f2b31f640f530643ee2f"
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;
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
  };
@@ -23,7 +23,7 @@ import { PopoverOverlayMixin } from './vaadin-popover-overlay-mixin.js';
23
23
  * @private
24
24
  */
25
25
  class PopoverOverlay extends PopoverOverlayMixin(
26
- DirMixin(ThemableMixin(LumoInjectionMixin(PolylitMixin(LitElement)))),
26
+ DirMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement)))),
27
27
  ) {
28
28
  static get is() {
29
29
  return 'vaadin-popover-overlay';
@@ -43,6 +43,38 @@ class PopoverOverlay extends PopoverOverlayMixin(
43
43
  </div>
44
44
  `;
45
45
  }
46
+
47
+ /**
48
+ * @override
49
+ * @protected
50
+ */
51
+ get _contentRoot() {
52
+ return this.owner;
53
+ }
54
+
55
+ /**
56
+ * @override
57
+ * @protected
58
+ */
59
+ get _modalRoot() {
60
+ return this.owner;
61
+ }
62
+
63
+ /**
64
+ * @protected
65
+ * @override
66
+ */
67
+ _attachOverlay() {
68
+ this.showPopover();
69
+ }
70
+
71
+ /**
72
+ * @protected
73
+ * @override
74
+ */
75
+ _detachOverlay() {
76
+ this.hidePopover();
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,8 @@ 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"
472
+ popover="manual"
486
473
  .renderer="${this.renderer}"
487
474
  .owner="${this}"
488
475
  theme="${ifDefined(this._theme)}"
@@ -504,11 +491,14 @@ class Popover extends PopoverPositionMixin(
504
491
  @opened-changed="${this.__onOpenedChanged}"
505
492
  .restoreFocusOnClose="${this.__shouldRestoreFocus}"
506
493
  .restoreFocusNode="${this.target}"
494
+ exportparts="backdrop, overlay, content, arrow"
507
495
  @vaadin-overlay-escape-press="${this.__onEscapePress}"
508
496
  @vaadin-overlay-outside-click="${this.__onOutsideClick}"
509
497
  @vaadin-overlay-open="${this.__onOverlayOpened}"
510
498
  @vaadin-overlay-closed="${this.__onOverlayClosed}"
511
- ></vaadin-popover-overlay>
499
+ >
500
+ <slot></slot>
501
+ </vaadin-popover-overlay>
512
502
  `;
513
503
  }
514
504
 
@@ -530,13 +520,43 @@ class Popover extends PopoverPositionMixin(
530
520
  ready() {
531
521
  super.ready();
532
522
 
533
- this._overlayElement = this.$[this.__overlayId];
523
+ this._overlayElement = this.$.overlay;
524
+ }
525
+
526
+ /** @protected */
527
+ updated(props) {
528
+ super.updated(props);
529
+
530
+ if (props.has('overlayRole')) {
531
+ this.setAttribute('role', this.overlayRole);
532
+ }
533
+
534
+ if (props.has('accessibleName')) {
535
+ if (this.accessibleName) {
536
+ this.setAttribute('aria-label', this.accessibleName);
537
+ } else {
538
+ this.removeAttribute('aria-label');
539
+ }
540
+ }
541
+
542
+ if (props.has('accessibleNameRef')) {
543
+ if (this.accessibleNameRef) {
544
+ this.setAttribute('aria-labelledby', this.accessibleNameRef);
545
+ } else {
546
+ this.removeAttribute('aria-labelledby');
547
+ }
548
+ }
534
549
  }
535
550
 
536
551
  /** @protected */
537
552
  connectedCallback() {
538
553
  super.connectedCallback();
539
554
 
555
+ // If no user ID is provided, set generated ID
556
+ if (!this.id) {
557
+ this.id = this.__generatedId;
558
+ }
559
+
540
560
  document.documentElement.addEventListener('click', this.__onGlobalClick, true);
541
561
  }
542
562
 
@@ -608,7 +628,7 @@ class Popover extends PopoverPositionMixin(
608
628
  effectiveTarget.setAttribute('aria-expanded', opened ? 'true' : 'false');
609
629
 
610
630
  if (opened) {
611
- effectiveTarget.setAttribute('aria-controls', this.__overlayId);
631
+ effectiveTarget.setAttribute('aria-controls', this.id);
612
632
  } else {
613
633
  effectiveTarget.removeAttribute('aria-controls');
614
634
  }
@@ -787,7 +807,7 @@ class Popover extends PopoverPositionMixin(
787
807
  return;
788
808
  }
789
809
 
790
- if ((this.__hasTrigger('focus') && this.__mouseDownInside) || this._overlayElement.contains(event.relatedTarget)) {
810
+ if ((this.__hasTrigger('focus') && this.__mouseDownInside) || this.contains(event.relatedTarget)) {
791
811
  return;
792
812
  }
793
813
 
@@ -815,7 +835,7 @@ class Popover extends PopoverPositionMixin(
815
835
  return;
816
836
  }
817
837
 
818
- if (this._overlayElement.contains(event.relatedTarget)) {
838
+ if (this.contains(event.relatedTarget)) {
819
839
  return;
820
840
  }
821
841
 
@@ -846,7 +866,8 @@ class Popover extends PopoverPositionMixin(
846
866
  if (
847
867
  (this.__hasTrigger('focus') && this.__mouseDownInside) ||
848
868
  event.relatedTarget === this.target ||
849
- this._overlayElement.contains(event.relatedTarget)
869
+ event.relatedTarget === this._overlayElement ||
870
+ this.contains(event.relatedTarget)
850
871
  ) {
851
872
  return;
852
873
  }
@@ -904,6 +925,11 @@ class Popover extends PopoverPositionMixin(
904
925
  }
905
926
 
906
927
  if (this.__hasTrigger('focus')) {
928
+ // Do not restore focus if closed on focusout on Tab
929
+ if (isKeyboardActive()) {
930
+ this.__shouldRestoreFocus = false;
931
+ }
932
+
907
933
  this._openedStateController.close(true);
908
934
  }
909
935
  }
@@ -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'] {
@@ -28,7 +24,7 @@ const popoverOverlay = css`
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-alpha8",
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-alpha8",
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
  }