@vaadin/popover 25.0.0-alpha6 → 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-alpha6",
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-alpha6",
41
- "@vaadin/component-base": "25.0.0-alpha6",
42
- "@vaadin/lit-renderer": "25.0.0-alpha6",
43
- "@vaadin/overlay": "25.0.0-alpha6",
44
- "@vaadin/vaadin-lumo-styles": "25.0.0-alpha6",
45
- "@vaadin/vaadin-themable-mixin": "25.0.0-alpha6",
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-alpha6",
50
- "@vaadin/test-runner-commands": "25.0.0-alpha6",
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": "cd1d084198d2b326c58d44bb39fa4845b71ce551"
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
  */
@@ -119,13 +113,13 @@ declare class Popover extends PopoverPositionMixin(
119
113
  * Set the height of the overlay.
120
114
  * If a unitless number is provided, pixels are assumed.
121
115
  */
122
- height: string;
116
+ height: string | null;
123
117
 
124
118
  /**
125
119
  * Set the width of the overlay.
126
120
  * If a unitless number is provided, pixels are assumed.
127
121
  */
128
- width: string;
122
+ width: string | null;
129
123
 
130
124
  /**
131
125
  * The delay in milliseconds before the popover is opened
@@ -18,7 +18,6 @@ import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixi
18
18
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
19
19
  import { generateUniqueId } from '@vaadin/component-base/src/unique-id-utils.js';
20
20
  import { isLastOverlay as isLastOverlayBase } from '@vaadin/overlay/src/vaadin-overlay-stack-mixin.js';
21
- import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
22
21
  import { ThemePropertyMixin } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
23
22
  import { PopoverPositionMixin } from './vaadin-popover-position-mixin.js';
24
23
  import { PopoverTargetMixin } from './vaadin-popover-target-mixin.js';
@@ -170,16 +169,13 @@ const isLastOverlay = (overlay) => {
170
169
  *
171
170
  * ### Styling
172
171
  *
173
- * `<vaadin-popover>` uses `<vaadin-popover-overlay>` internal
174
- * themable component as the actual visible overlay.
175
- *
176
- * See [`<vaadin-overlay>`](#/elements/vaadin-overlay) documentation
177
- * for `<vaadin-popover-overlay>` parts.
178
- *
179
- * In addition to `<vaadin-overlay>` parts, the following parts are available for styling:
172
+ * The following shadow DOM parts are available for styling:
180
173
  *
181
174
  * Part name | Description
182
175
  * -----------------|-------------------------------------------
176
+ * `backdrop` | Backdrop of the overlay
177
+ * `overlay` | The overlay container
178
+ * `content` | The overlay content
183
179
  * `arrow` | Optional arrow pointing to the target when using `theme="arrow"`
184
180
  *
185
181
  * The following state attributes are available for styling:
@@ -188,9 +184,6 @@ const isLastOverlay = (overlay) => {
188
184
  * -----------------|----------------------------------------
189
185
  * `position` | Reflects the `position` property value.
190
186
  *
191
- * Note: the `theme` attribute value set on `<vaadin-popover>` is
192
- * propagated to the internal `<vaadin-popover-overlay>` component.
193
- *
194
187
  * ### Custom CSS Properties
195
188
  *
196
189
  * The following custom CSS properties are available on the `<vaadin-popover>` element:
@@ -216,7 +209,7 @@ const isLastOverlay = (overlay) => {
216
209
  * @mixes ThemePropertyMixin
217
210
  */
218
211
  class Popover extends PopoverPositionMixin(
219
- PopoverTargetMixin(OverlayClassMixin(ThemePropertyMixin(ElementMixin(LumoInjectionMixin(PolylitMixin(LitElement)))))),
212
+ PopoverTargetMixin(OverlayClassMixin(ThemePropertyMixin(ElementMixin(PolylitMixin(LitElement))))),
220
213
  ) {
221
214
  static get is() {
222
215
  return 'vaadin-popover';
@@ -225,7 +218,7 @@ class Popover extends PopoverPositionMixin(
225
218
  static get styles() {
226
219
  return css`
227
220
  :host {
228
- display: none !important;
221
+ display: contents;
229
222
  }
230
223
  `;
231
224
  }
@@ -233,7 +226,7 @@ class Popover extends PopoverPositionMixin(
233
226
  static get properties() {
234
227
  return {
235
228
  /**
236
- * String used to label the overlay to screen reader users.
229
+ * String used to label the popover to screen reader users.
237
230
  *
238
231
  * @attr {string} accessible-name
239
232
  */
@@ -242,7 +235,7 @@ class Popover extends PopoverPositionMixin(
242
235
  },
243
236
 
244
237
  /**
245
- * 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.
246
239
  *
247
240
  * @attr {string} accessible-name-ref
248
241
  */
@@ -416,11 +409,6 @@ class Popover extends PopoverPositionMixin(
416
409
  value: false,
417
410
  sync: true,
418
411
  },
419
-
420
- /** @private */
421
- __overlayId: {
422
- type: String,
423
- },
424
412
  };
425
413
  }
426
414
 
@@ -461,7 +449,7 @@ class Popover extends PopoverPositionMixin(
461
449
  constructor() {
462
450
  super();
463
451
 
464
- this.__overlayId = `vaadin-popover-${generateUniqueId()}`;
452
+ this.__generatedId = `vaadin-popover-${generateUniqueId()}`;
465
453
 
466
454
  this.__onGlobalClick = this.__onGlobalClick.bind(this);
467
455
  this.__onGlobalKeyDown = this.__onGlobalKeyDown.bind(this);
@@ -480,10 +468,8 @@ class Popover extends PopoverPositionMixin(
480
468
 
481
469
  return html`
482
470
  <vaadin-popover-overlay
483
- id="${this.__overlayId}"
484
- role="${this.overlayRole}"
485
- aria-label="${ifDefined(this.accessibleName)}"
486
- aria-labelledby="${ifDefined(this.accessibleNameRef)}"
471
+ id="overlay"
472
+ popover="manual"
487
473
  .renderer="${this.renderer}"
488
474
  .owner="${this}"
489
475
  theme="${ifDefined(this._theme)}"
@@ -505,11 +491,14 @@ class Popover extends PopoverPositionMixin(
505
491
  @opened-changed="${this.__onOpenedChanged}"
506
492
  .restoreFocusOnClose="${this.__shouldRestoreFocus}"
507
493
  .restoreFocusNode="${this.target}"
494
+ exportparts="backdrop, overlay, content, arrow"
508
495
  @vaadin-overlay-escape-press="${this.__onEscapePress}"
509
496
  @vaadin-overlay-outside-click="${this.__onOutsideClick}"
510
497
  @vaadin-overlay-open="${this.__onOverlayOpened}"
511
498
  @vaadin-overlay-closed="${this.__onOverlayClosed}"
512
- ></vaadin-popover-overlay>
499
+ >
500
+ <slot></slot>
501
+ </vaadin-popover-overlay>
513
502
  `;
514
503
  }
515
504
 
@@ -531,13 +520,43 @@ class Popover extends PopoverPositionMixin(
531
520
  ready() {
532
521
  super.ready();
533
522
 
534
- 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
+ }
535
549
  }
536
550
 
537
551
  /** @protected */
538
552
  connectedCallback() {
539
553
  super.connectedCallback();
540
554
 
555
+ // If no user ID is provided, set generated ID
556
+ if (!this.id) {
557
+ this.id = this.__generatedId;
558
+ }
559
+
541
560
  document.documentElement.addEventListener('click', this.__onGlobalClick, true);
542
561
  }
543
562
 
@@ -609,7 +628,7 @@ class Popover extends PopoverPositionMixin(
609
628
  effectiveTarget.setAttribute('aria-expanded', opened ? 'true' : 'false');
610
629
 
611
630
  if (opened) {
612
- effectiveTarget.setAttribute('aria-controls', this.__overlayId);
631
+ effectiveTarget.setAttribute('aria-controls', this.id);
613
632
  } else {
614
633
  effectiveTarget.removeAttribute('aria-controls');
615
634
  }
@@ -788,7 +807,7 @@ class Popover extends PopoverPositionMixin(
788
807
  return;
789
808
  }
790
809
 
791
- if ((this.__hasTrigger('focus') && this.__mouseDownInside) || this._overlayElement.contains(event.relatedTarget)) {
810
+ if ((this.__hasTrigger('focus') && this.__mouseDownInside) || this.contains(event.relatedTarget)) {
792
811
  return;
793
812
  }
794
813
 
@@ -816,7 +835,7 @@ class Popover extends PopoverPositionMixin(
816
835
  return;
817
836
  }
818
837
 
819
- if (this._overlayElement.contains(event.relatedTarget)) {
838
+ if (this.contains(event.relatedTarget)) {
820
839
  return;
821
840
  }
822
841
 
@@ -847,7 +866,8 @@ class Popover extends PopoverPositionMixin(
847
866
  if (
848
867
  (this.__hasTrigger('focus') && this.__mouseDownInside) ||
849
868
  event.relatedTarget === this.target ||
850
- this._overlayElement.contains(event.relatedTarget)
869
+ event.relatedTarget === this._overlayElement ||
870
+ this.contains(event.relatedTarget)
851
871
  ) {
852
872
  return;
853
873
  }
@@ -905,6 +925,11 @@ class Popover extends PopoverPositionMixin(
905
925
  }
906
926
 
907
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
+
908
933
  this._openedStateController.close(true);
909
934
  }
910
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-alpha6",
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-alpha6/#/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-alpha6",
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-alpha6/#/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
  }