@vaadin/overlay 25.3.0-alpha8 → 25.3.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/custom-elements.json +102 -6
- package/package.json +9 -9
- package/src/styles/vaadin-overlay-animation-base-styles.d.ts +10 -0
- package/src/styles/vaadin-overlay-animation-base-styles.js +102 -0
- package/src/styles/vaadin-overlay-base-styles.d.ts +8 -0
- package/src/styles/vaadin-overlay-base-styles.js +4 -1
- package/src/vaadin-overlay-focus-mixin.d.ts +20 -4
- package/src/vaadin-overlay-focus-mixin.js +42 -6
- package/src/vaadin-overlay-mixin.js +2 -17
- package/src/vaadin-overlay-utils.d.ts +7 -0
- package/src/vaadin-overlay-utils.js +18 -0
package/custom-elements.json
CHANGED
|
@@ -26,6 +26,16 @@
|
|
|
26
26
|
"description": "",
|
|
27
27
|
"name": "OverlayFocusMixin",
|
|
28
28
|
"members": [
|
|
29
|
+
{
|
|
30
|
+
"kind": "field",
|
|
31
|
+
"name": "autofocus",
|
|
32
|
+
"privacy": "public",
|
|
33
|
+
"type": {
|
|
34
|
+
"text": "boolean"
|
|
35
|
+
},
|
|
36
|
+
"description": "Set to true to move focus into the overlay automatically on open.\n\nFocus moves to the first tabbable element in the tab order. This\ncan be the overlay itself if it has `tabindex` attribute set to `0`\non the host element or the `overlay` shadow DOM part.",
|
|
37
|
+
"attribute": "autofocus"
|
|
38
|
+
},
|
|
29
39
|
{
|
|
30
40
|
"kind": "field",
|
|
31
41
|
"name": "focusTrap",
|
|
@@ -33,7 +43,7 @@
|
|
|
33
43
|
"type": {
|
|
34
44
|
"text": "boolean"
|
|
35
45
|
},
|
|
36
|
-
"description": "
|
|
46
|
+
"description": "Set to true to move focus into the overlay automatically on open\nand keep it inside: Tab and Shift+Tab cycle through the overlay's\ncontent until the overlay is closed.\n\nFocus moves to the first tabbable element in the tab order. This\ncan be the overlay itself if it has `tabindex` attribute set to `0`\non the host element or the `overlay` shadow DOM part.",
|
|
37
47
|
"attribute": "focus-trap"
|
|
38
48
|
},
|
|
39
49
|
{
|
|
@@ -58,12 +68,20 @@
|
|
|
58
68
|
}
|
|
59
69
|
],
|
|
60
70
|
"attributes": [
|
|
71
|
+
{
|
|
72
|
+
"name": "autofocus",
|
|
73
|
+
"type": {
|
|
74
|
+
"text": "boolean"
|
|
75
|
+
},
|
|
76
|
+
"description": "Set to true to move focus into the overlay automatically on open.\n\nFocus moves to the first tabbable element in the tab order. This\ncan be the overlay itself if it has `tabindex` attribute set to `0`\non the host element or the `overlay` shadow DOM part.",
|
|
77
|
+
"fieldName": "autofocus"
|
|
78
|
+
},
|
|
61
79
|
{
|
|
62
80
|
"name": "focus-trap",
|
|
63
81
|
"type": {
|
|
64
82
|
"text": "boolean"
|
|
65
83
|
},
|
|
66
|
-
"description": "
|
|
84
|
+
"description": "Set to true to move focus into the overlay automatically on open\nand keep it inside: Tab and Shift+Tab cycle through the overlay's\ncontent until the overlay is closed.\n\nFocus moves to the first tabbable element in the tab order. This\ncan be the overlay itself if it has `tabindex` attribute set to `0`\non the host element or the `overlay` shadow DOM part.",
|
|
67
85
|
"fieldName": "focusTrap"
|
|
68
86
|
},
|
|
69
87
|
{
|
|
@@ -110,6 +128,20 @@
|
|
|
110
128
|
"description": "",
|
|
111
129
|
"name": "OverlayMixin",
|
|
112
130
|
"members": [
|
|
131
|
+
{
|
|
132
|
+
"kind": "field",
|
|
133
|
+
"name": "autofocus",
|
|
134
|
+
"privacy": "public",
|
|
135
|
+
"type": {
|
|
136
|
+
"text": "boolean"
|
|
137
|
+
},
|
|
138
|
+
"description": "Set to true to move focus into the overlay automatically on open.\n\nFocus moves to the first tabbable element in the tab order. This\ncan be the overlay itself if it has `tabindex` attribute set to `0`\non the host element or the `overlay` shadow DOM part.",
|
|
139
|
+
"attribute": "autofocus",
|
|
140
|
+
"inheritedFrom": {
|
|
141
|
+
"name": "OverlayFocusMixin",
|
|
142
|
+
"module": "src/vaadin-overlay-focus-mixin.js"
|
|
143
|
+
}
|
|
144
|
+
},
|
|
113
145
|
{
|
|
114
146
|
"kind": "method",
|
|
115
147
|
"name": "bringToFront",
|
|
@@ -138,7 +170,7 @@
|
|
|
138
170
|
"type": {
|
|
139
171
|
"text": "boolean"
|
|
140
172
|
},
|
|
141
|
-
"description": "
|
|
173
|
+
"description": "Set to true to move focus into the overlay automatically on open\nand keep it inside: Tab and Shift+Tab cycle through the overlay's\ncontent until the overlay is closed.\n\nFocus moves to the first tabbable element in the tab order. This\ncan be the overlay itself if it has `tabindex` attribute set to `0`\non the host element or the `overlay` shadow DOM part.",
|
|
142
174
|
"attribute": "focus-trap",
|
|
143
175
|
"inheritedFrom": {
|
|
144
176
|
"name": "OverlayFocusMixin",
|
|
@@ -284,12 +316,24 @@
|
|
|
284
316
|
}
|
|
285
317
|
],
|
|
286
318
|
"attributes": [
|
|
319
|
+
{
|
|
320
|
+
"name": "autofocus",
|
|
321
|
+
"type": {
|
|
322
|
+
"text": "boolean"
|
|
323
|
+
},
|
|
324
|
+
"description": "Set to true to move focus into the overlay automatically on open.\n\nFocus moves to the first tabbable element in the tab order. This\ncan be the overlay itself if it has `tabindex` attribute set to `0`\non the host element or the `overlay` shadow DOM part.",
|
|
325
|
+
"fieldName": "autofocus",
|
|
326
|
+
"inheritedFrom": {
|
|
327
|
+
"name": "OverlayFocusMixin",
|
|
328
|
+
"module": "src/vaadin-overlay-focus-mixin.js"
|
|
329
|
+
}
|
|
330
|
+
},
|
|
287
331
|
{
|
|
288
332
|
"name": "focus-trap",
|
|
289
333
|
"type": {
|
|
290
334
|
"text": "boolean"
|
|
291
335
|
},
|
|
292
|
-
"description": "
|
|
336
|
+
"description": "Set to true to move focus into the overlay automatically on open\nand keep it inside: Tab and Shift+Tab cycle through the overlay's\ncontent until the overlay is closed.\n\nFocus moves to the first tabbable element in the tab order. This\ncan be the overlay itself if it has `tabindex` attribute set to `0`\non the host element or the `overlay` shadow DOM part.",
|
|
293
337
|
"fieldName": "focusTrap",
|
|
294
338
|
"inheritedFrom": {
|
|
295
339
|
"name": "OverlayFocusMixin",
|
|
@@ -593,6 +637,24 @@
|
|
|
593
637
|
"name": "rootMargin",
|
|
594
638
|
"default": "`${-insetTop}px ${-insetRight}px ${-insetBottom}px ${-insetLeft}px`"
|
|
595
639
|
},
|
|
640
|
+
{
|
|
641
|
+
"kind": "function",
|
|
642
|
+
"name": "shouldAnimate",
|
|
643
|
+
"parameters": [
|
|
644
|
+
{
|
|
645
|
+
"name": "element",
|
|
646
|
+
"type": {
|
|
647
|
+
"text": "HTMLElement"
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
],
|
|
651
|
+
"description": "Detect whether an animation runs on the given element, so that its end can be\nawaited before the element is hidden or removed. An element that is not rendered,\nhas no animation name, or has a zero duration does not fire `animationend`.",
|
|
652
|
+
"return": {
|
|
653
|
+
"type": {
|
|
654
|
+
"text": "boolean"
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
},
|
|
596
658
|
{
|
|
597
659
|
"kind": "function",
|
|
598
660
|
"name": "setOverlayStateAttribute",
|
|
@@ -631,6 +693,14 @@
|
|
|
631
693
|
"module": "src/vaadin-overlay-utils.js"
|
|
632
694
|
}
|
|
633
695
|
},
|
|
696
|
+
{
|
|
697
|
+
"kind": "js",
|
|
698
|
+
"name": "shouldAnimate",
|
|
699
|
+
"declaration": {
|
|
700
|
+
"name": "shouldAnimate",
|
|
701
|
+
"module": "src/vaadin-overlay-utils.js"
|
|
702
|
+
}
|
|
703
|
+
},
|
|
634
704
|
{
|
|
635
705
|
"kind": "js",
|
|
636
706
|
"name": "setOverlayStateAttribute",
|
|
@@ -650,6 +720,20 @@
|
|
|
650
720
|
"description": "`<vaadin-overlay>` is a Web Component for creating overlays. The content of the overlay\ncan be populated imperatively by using `renderer` callback function.\n\n### Rendering\n\nThe renderer function provides `root`, `owner`, `model` arguments when applicable.\nGenerate DOM content by using `model` object properties if needed, append it to the `root`\nelement and control the state of the host element by accessing `owner`. Before generating new\ncontent, users are able to check if there is already content in `root` for reusing it.\n\n```html\n<vaadin-overlay id=\"overlay\"></vaadin-overlay>\n```\n```js\nconst overlay = document.querySelector('#overlay');\noverlay.renderer = function(root) {\n root.textContent = \"Overlay content\";\n};\n```\n\nRenderer is called on the opening of the overlay and each time the related model is updated.\nDOM generated during the renderer call can be reused\nin the next renderer call and will be provided with the `root` argument.\nOn first call it will be empty.\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` | Container for position/sizing/alignment of the content\n`content` | Content of the overlay\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n----------|------------\n`opening` | Applied just after the overlay is opened. You can apply a CSS animation for this state.\n`closing` | Applied just before the overlay is closed. You can apply a CSS animation for this state.\n\nThe following custom CSS properties are available for styling:\n\nCustom CSS property | Description | Default value\n---|---|---\n`--vaadin-overlay-viewport-bottom` | Bottom offset of the visible viewport area | `0` or detected offset\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
|
|
651
721
|
"name": "Overlay",
|
|
652
722
|
"members": [
|
|
723
|
+
{
|
|
724
|
+
"kind": "field",
|
|
725
|
+
"name": "autofocus",
|
|
726
|
+
"privacy": "public",
|
|
727
|
+
"type": {
|
|
728
|
+
"text": "boolean"
|
|
729
|
+
},
|
|
730
|
+
"description": "Set to true to move focus into the overlay automatically on open.\n\nFocus moves to the first tabbable element in the tab order. This\ncan be the overlay itself if it has `tabindex` attribute set to `0`\non the host element or the `overlay` shadow DOM part.",
|
|
731
|
+
"attribute": "autofocus",
|
|
732
|
+
"inheritedFrom": {
|
|
733
|
+
"name": "OverlayFocusMixin",
|
|
734
|
+
"module": "src/vaadin-overlay-focus-mixin.js"
|
|
735
|
+
}
|
|
736
|
+
},
|
|
653
737
|
{
|
|
654
738
|
"kind": "method",
|
|
655
739
|
"name": "bringToFront",
|
|
@@ -682,7 +766,7 @@
|
|
|
682
766
|
"type": {
|
|
683
767
|
"text": "boolean"
|
|
684
768
|
},
|
|
685
|
-
"description": "
|
|
769
|
+
"description": "Set to true to move focus into the overlay automatically on open\nand keep it inside: Tab and Shift+Tab cycle through the overlay's\ncontent until the overlay is closed.\n\nFocus moves to the first tabbable element in the tab order. This\ncan be the overlay itself if it has `tabindex` attribute set to `0`\non the host element or the `overlay` shadow DOM part.",
|
|
686
770
|
"attribute": "focus-trap",
|
|
687
771
|
"inheritedFrom": {
|
|
688
772
|
"name": "OverlayFocusMixin",
|
|
@@ -937,12 +1021,24 @@
|
|
|
937
1021
|
"tagName": "vaadin-overlay",
|
|
938
1022
|
"customElement": true,
|
|
939
1023
|
"attributes": [
|
|
1024
|
+
{
|
|
1025
|
+
"name": "autofocus",
|
|
1026
|
+
"type": {
|
|
1027
|
+
"text": "boolean"
|
|
1028
|
+
},
|
|
1029
|
+
"description": "Set to true to move focus into the overlay automatically on open.\n\nFocus moves to the first tabbable element in the tab order. This\ncan be the overlay itself if it has `tabindex` attribute set to `0`\non the host element or the `overlay` shadow DOM part.",
|
|
1030
|
+
"fieldName": "autofocus",
|
|
1031
|
+
"inheritedFrom": {
|
|
1032
|
+
"name": "OverlayFocusMixin",
|
|
1033
|
+
"module": "src/vaadin-overlay-focus-mixin.js"
|
|
1034
|
+
}
|
|
1035
|
+
},
|
|
940
1036
|
{
|
|
941
1037
|
"name": "focus-trap",
|
|
942
1038
|
"type": {
|
|
943
1039
|
"text": "boolean"
|
|
944
1040
|
},
|
|
945
|
-
"description": "
|
|
1041
|
+
"description": "Set to true to move focus into the overlay automatically on open\nand keep it inside: Tab and Shift+Tab cycle through the overlay's\ncontent until the overlay is closed.\n\nFocus moves to the first tabbable element in the tab order. This\ncan be the overlay itself if it has `tabindex` attribute set to `0`\non the host element or the `overlay` shadow DOM part.",
|
|
946
1042
|
"fieldName": "focusTrap",
|
|
947
1043
|
"inheritedFrom": {
|
|
948
1044
|
"name": "OverlayFocusMixin",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/overlay",
|
|
3
|
-
"version": "25.3.0-
|
|
3
|
+
"version": "25.3.0-alpha9",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -34,19 +34,19 @@
|
|
|
34
34
|
],
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
37
|
-
"@vaadin/a11y-base": "25.3.0-
|
|
38
|
-
"@vaadin/component-base": "25.3.0-
|
|
39
|
-
"@vaadin/vaadin-themable-mixin": "25.3.0-
|
|
37
|
+
"@vaadin/a11y-base": "25.3.0-alpha9",
|
|
38
|
+
"@vaadin/component-base": "25.3.0-alpha9",
|
|
39
|
+
"@vaadin/vaadin-themable-mixin": "25.3.0-alpha9",
|
|
40
40
|
"lit": "^3.0.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@vaadin/aura": "25.3.0-
|
|
44
|
-
"@vaadin/chai-plugins": "25.3.0-
|
|
45
|
-
"@vaadin/test-runner-commands": "25.3.0-
|
|
43
|
+
"@vaadin/aura": "25.3.0-alpha9",
|
|
44
|
+
"@vaadin/chai-plugins": "25.3.0-alpha9",
|
|
45
|
+
"@vaadin/test-runner-commands": "25.3.0-alpha9",
|
|
46
46
|
"@vaadin/testing-helpers": "^2.0.0",
|
|
47
|
-
"@vaadin/vaadin-lumo-styles": "25.3.0-
|
|
47
|
+
"@vaadin/vaadin-lumo-styles": "25.3.0-alpha9",
|
|
48
48
|
"sinon": "^22.0.0"
|
|
49
49
|
},
|
|
50
50
|
"customElements": "custom-elements.json",
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "cb915ebde095ec5b94a87af93dd4530f51984c52"
|
|
52
52
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2017 - 2026 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 overlayAnimationProperties: CSSResult;
|
|
9
|
+
|
|
10
|
+
export const overlayAnimationStyles: CSSResult;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2017 - 2026 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { css, unsafeCSS } from 'lit';
|
|
7
|
+
import { registerCSSProperty } from '@vaadin/component-base/src/css-utils.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The custom properties that make up the overlay animation CSS API. Both the
|
|
11
|
+
* property registrations and the `overlayAnimationProperties` snippet below are
|
|
12
|
+
* derived from this list, so a new property only needs to be added here.
|
|
13
|
+
*
|
|
14
|
+
* Only the closed state is part of the API. The opened state is left out of the
|
|
15
|
+
* keyframes so that it comes from the part itself, see the keyframes below.
|
|
16
|
+
*
|
|
17
|
+
* `--vaadin-overlay-transform-closed` has no initial value, which makes it resolve
|
|
18
|
+
* to `none` in the keyframes unless a theme sets it.
|
|
19
|
+
*/
|
|
20
|
+
const animationProperties = [
|
|
21
|
+
{ name: '--vaadin-overlay-animation-duration', syntax: '<time>', initialValue: '0s' },
|
|
22
|
+
{ name: '--vaadin-overlay-animation-delay', syntax: '<time>', initialValue: '0s' },
|
|
23
|
+
{ name: '--vaadin-overlay-animation-timing-function', syntax: '*', initialValue: 'ease' },
|
|
24
|
+
{ name: '--vaadin-overlay-opacity-closed', syntax: '<number>', initialValue: '0' },
|
|
25
|
+
{ name: '--vaadin-overlay-translate-closed', syntax: '<length>+ | <percentage>+', initialValue: '0px' },
|
|
26
|
+
{ name: '--vaadin-overlay-scale-closed', syntax: '<number> | <percentage>', initialValue: '1' },
|
|
27
|
+
{ name: '--vaadin-overlay-transform-closed', syntax: '*' },
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
animationProperties.forEach((property) => {
|
|
31
|
+
registerCSSProperty({ inherits: false, ...property });
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The overlay animation properties as a set of `inherit` declarations. The properties are
|
|
36
|
+
* registered as non-inheriting, so components with more than one shadow root boundary
|
|
37
|
+
* between the host and the overlay need to forward them explicitly.
|
|
38
|
+
*/
|
|
39
|
+
export const overlayAnimationProperties = unsafeCSS(
|
|
40
|
+
animationProperties.map(({ name }) => `${name}: inherit;`).join('\n'),
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
export const overlayAnimationStyles = css`
|
|
44
|
+
:host,
|
|
45
|
+
[part='overlay'],
|
|
46
|
+
[part='backdrop'] {
|
|
47
|
+
${overlayAnimationProperties}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
:host(:where([opening], [closing])) {
|
|
51
|
+
/* This empty animation only reports the state, the parts run the visible animation */
|
|
52
|
+
animation-name: --no-op;
|
|
53
|
+
animation-duration: var(--vaadin-overlay-animation-duration);
|
|
54
|
+
animation-delay: var(--vaadin-overlay-animation-delay);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
:host(:where([closing])) [part='overlay'],
|
|
58
|
+
:host(:where([closing])) ::slotted(*) {
|
|
59
|
+
pointer-events: none !important;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
:host(:where([opening], [closing])) :is([part='overlay'], [part='backdrop']) {
|
|
63
|
+
animation-name: --fade, --transform;
|
|
64
|
+
animation-duration: var(--vaadin-overlay-animation-duration);
|
|
65
|
+
animation-timing-function: var(--vaadin-overlay-animation-timing-function);
|
|
66
|
+
animation-delay: var(--vaadin-overlay-animation-delay);
|
|
67
|
+
/* Fill backwards only, so the closed value applies during the delay without overriding theme styles */
|
|
68
|
+
animation-fill-mode: backwards;
|
|
69
|
+
|
|
70
|
+
@media (prefers-reduced-motion) {
|
|
71
|
+
animation-name: --fade;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
:host(:where([opening], [closing])) [part='backdrop'] {
|
|
76
|
+
animation-name: --fade;
|
|
77
|
+
animation-timing-function: linear;
|
|
78
|
+
--vaadin-overlay-opacity-closed: 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
:host(:where([closing])) :is([part='overlay'], [part='backdrop']) {
|
|
82
|
+
animation-direction: reverse;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@keyframes --no-op {
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* Only the closed state is declared, so the animations end at the value the part already has */
|
|
89
|
+
@keyframes --transform {
|
|
90
|
+
0% {
|
|
91
|
+
transform: var(--vaadin-overlay-transform-closed);
|
|
92
|
+
translate: var(--vaadin-overlay-translate-closed);
|
|
93
|
+
scale: var(--vaadin-overlay-scale-closed);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@keyframes --fade {
|
|
98
|
+
0% {
|
|
99
|
+
opacity: var(--vaadin-overlay-opacity-closed);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
`;
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import '@vaadin/component-base/src/styles/style-props.js';
|
|
7
7
|
import { css } from 'lit';
|
|
8
|
+
import { overlayAnimationStyles } from './vaadin-overlay-animation-base-styles.js';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
const overlayBase = css`
|
|
10
11
|
:host {
|
|
11
12
|
z-index: 200;
|
|
12
13
|
position: fixed;
|
|
@@ -103,3 +104,5 @@ export const overlayStyles = css`
|
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
`;
|
|
107
|
+
|
|
108
|
+
export const overlayStyles = [overlayBase, overlayAnimationStyles];
|
|
@@ -11,12 +11,27 @@ export declare function OverlayFocusMixin<T extends Constructor<HTMLElement>>(
|
|
|
11
11
|
|
|
12
12
|
export declare class OverlayFocusMixinClass {
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* Set to true to move focus into the overlay automatically on open
|
|
15
|
+
* and keep it inside: Tab and Shift+Tab cycle through the overlay's
|
|
16
|
+
* content until the overlay is closed.
|
|
17
|
+
*
|
|
18
|
+
* Focus moves to the first tabbable element in the tab order. This
|
|
19
|
+
* can be the overlay itself if it has `tabindex` attribute set to `0`
|
|
20
|
+
* on the host element or the `overlay` shadow DOM part.
|
|
21
|
+
*
|
|
16
22
|
* @attr {boolean} focus-trap
|
|
17
23
|
*/
|
|
18
24
|
focusTrap: boolean;
|
|
19
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Set to true to move focus into the overlay automatically on open.
|
|
28
|
+
*
|
|
29
|
+
* Focus moves to the first tabbable element in the tab order. This
|
|
30
|
+
* can be the overlay itself if it has `tabindex` attribute set to `0`
|
|
31
|
+
* on the host element or the `overlay` shadow DOM part.
|
|
32
|
+
*/
|
|
33
|
+
autofocus: boolean;
|
|
34
|
+
|
|
20
35
|
/**
|
|
21
36
|
* Set to true to enable restoring of focus when overlay is closed.
|
|
22
37
|
* @attr {boolean} restore-focus-on-close
|
|
@@ -40,8 +55,9 @@ export declare class OverlayFocusMixinClass {
|
|
|
40
55
|
protected _saveFocus(): void;
|
|
41
56
|
|
|
42
57
|
/**
|
|
43
|
-
* Sets up focus after the overlay opening has completed:
|
|
44
|
-
*
|
|
58
|
+
* Sets up focus after the overlay opening has completed: moves focus into
|
|
59
|
+
* the overlay if `autofocus` is enabled, and traps focus within the overlay
|
|
60
|
+
* if `focusTrap` is enabled.
|
|
45
61
|
*/
|
|
46
62
|
protected _initFocus(): void;
|
|
47
63
|
|
|
@@ -5,15 +5,27 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { FocusRestorationController } from '@vaadin/a11y-base/src/focus-restoration-controller.js';
|
|
7
7
|
import { FocusTrapController } from '@vaadin/a11y-base/src/focus-trap-controller.js';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
getDeepActiveElement,
|
|
10
|
+
getTabbableElements,
|
|
11
|
+
isElementFocused,
|
|
12
|
+
isElementHidden,
|
|
13
|
+
isKeyboardActive,
|
|
14
|
+
} from '@vaadin/a11y-base/src/focus-utils.js';
|
|
9
15
|
|
|
10
16
|
export const OverlayFocusMixin = (superClass) =>
|
|
11
17
|
class OverlayFocusMixin extends superClass {
|
|
12
18
|
static get properties() {
|
|
13
19
|
return {
|
|
14
20
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
21
|
+
* Set to true to move focus into the overlay automatically on open
|
|
22
|
+
* and keep it inside: Tab and Shift+Tab cycle through the overlay's
|
|
23
|
+
* content until the overlay is closed.
|
|
24
|
+
*
|
|
25
|
+
* Focus moves to the first tabbable element in the tab order. This
|
|
26
|
+
* can be the overlay itself if it has `tabindex` attribute set to `0`
|
|
27
|
+
* on the host element or the `overlay` shadow DOM part.
|
|
28
|
+
*
|
|
17
29
|
* @attr {boolean} focus-trap
|
|
18
30
|
*/
|
|
19
31
|
focusTrap: {
|
|
@@ -21,6 +33,18 @@ export const OverlayFocusMixin = (superClass) =>
|
|
|
21
33
|
value: false,
|
|
22
34
|
},
|
|
23
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Set to true to move focus into the overlay automatically on open.
|
|
38
|
+
*
|
|
39
|
+
* Focus moves to the first tabbable element in the tab order. This
|
|
40
|
+
* can be the overlay itself if it has `tabindex` attribute set to `0`
|
|
41
|
+
* on the host element or the `overlay` shadow DOM part.
|
|
42
|
+
*/
|
|
43
|
+
autofocus: {
|
|
44
|
+
type: Boolean,
|
|
45
|
+
value: false,
|
|
46
|
+
},
|
|
47
|
+
|
|
24
48
|
/**
|
|
25
49
|
* Set to true to enable restoring of focus when overlay is closed.
|
|
26
50
|
* @attr {boolean} restore-focus-on-close
|
|
@@ -103,13 +127,25 @@ export const OverlayFocusMixin = (superClass) =>
|
|
|
103
127
|
}
|
|
104
128
|
|
|
105
129
|
/**
|
|
106
|
-
* Sets up focus after the overlay opening has completed:
|
|
107
|
-
*
|
|
130
|
+
* Sets up focus after the overlay opening has completed: moves focus into
|
|
131
|
+
* the overlay if `autofocus` is enabled, and traps focus within the overlay
|
|
132
|
+
* if `focusTrap` is enabled.
|
|
108
133
|
*
|
|
109
134
|
* @protected
|
|
110
135
|
*/
|
|
111
136
|
_initFocus() {
|
|
112
|
-
if (
|
|
137
|
+
if (isElementHidden(this._focusRoot)) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (this.autofocus) {
|
|
142
|
+
const tabbables = getTabbableElements(this._focusRoot);
|
|
143
|
+
if (!tabbables.some(isElementFocused)) {
|
|
144
|
+
tabbables[0]?.focus({ focusVisible: isKeyboardActive() });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (this.focusTrap) {
|
|
113
149
|
this.__focusTrapController.trapFocus(this._focusRoot);
|
|
114
150
|
}
|
|
115
151
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { isIOS } from '@vaadin/component-base/src/browser-utils.js';
|
|
7
7
|
import { OverlayFocusMixin } from './vaadin-overlay-focus-mixin.js';
|
|
8
8
|
import { OverlayStackMixin } from './vaadin-overlay-stack-mixin.js';
|
|
9
|
-
import { setOverlayStateAttribute } from './vaadin-overlay-utils.js';
|
|
9
|
+
import { setOverlayStateAttribute, shouldAnimate } from './vaadin-overlay-utils.js';
|
|
10
10
|
|
|
11
11
|
export const OverlayMixin = (superClass) =>
|
|
12
12
|
class OverlayMixin extends OverlayFocusMixin(OverlayStackMixin(superClass)) {
|
|
@@ -133,14 +133,6 @@ export const OverlayMixin = (superClass) =>
|
|
|
133
133
|
this.$.backdrop.addEventListener('click', () => {});
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
this.addEventListener('mouseup', () => {
|
|
137
|
-
// In Chrome, focus moves to body on overlay content mousedown
|
|
138
|
-
// See https://github.com/vaadin/flow-components/issues/5507
|
|
139
|
-
if (document.activeElement === document.body && this.$.overlay.getAttribute('tabindex') === '0') {
|
|
140
|
-
this.$.overlay.focus();
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
|
|
144
136
|
this.addEventListener('animationcancel', () => {
|
|
145
137
|
this._flushAnimation('opening');
|
|
146
138
|
this._flushAnimation('closing');
|
|
@@ -405,14 +397,7 @@ export const OverlayMixin = (superClass) =>
|
|
|
405
397
|
* @private
|
|
406
398
|
*/
|
|
407
399
|
_shouldAnimate() {
|
|
408
|
-
|
|
409
|
-
const name = style.getPropertyValue('animation-name');
|
|
410
|
-
const hasDuration = style
|
|
411
|
-
.getPropertyValue('animation-duration')
|
|
412
|
-
.split(',')
|
|
413
|
-
.some((duration) => parseFloat(duration) > 0);
|
|
414
|
-
const hidden = style.getPropertyValue('display') === 'none';
|
|
415
|
-
return !hidden && name && name !== 'none' && hasDuration;
|
|
400
|
+
return shouldAnimate(this);
|
|
416
401
|
}
|
|
417
402
|
|
|
418
403
|
/**
|
|
@@ -12,6 +12,13 @@
|
|
|
12
12
|
*/
|
|
13
13
|
export function observeMove(element: HTMLElement, callback: () => void): () => void;
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Detect whether an animation runs on the given element, so that its end can be
|
|
17
|
+
* awaited before the element is hidden or removed. An element that is not rendered,
|
|
18
|
+
* has no animation name, or has a zero duration does not fire `animationend`.
|
|
19
|
+
*/
|
|
20
|
+
export function shouldAnimate(element: HTMLElement): boolean;
|
|
21
|
+
|
|
15
22
|
/**
|
|
16
23
|
* Toggle the state attribute on the overlay element and also its owner element. This allows targeting state attributes
|
|
17
24
|
* in the light DOM in case the overlay is in the shadow DOM of its owner.
|
|
@@ -85,6 +85,24 @@ export function observeMove(element, callback) {
|
|
|
85
85
|
return cleanup;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Detect whether an animation runs on the given element, so that its end can be
|
|
90
|
+
* awaited before the element is hidden or removed. An element that is not rendered,
|
|
91
|
+
* has no animation name, or has a zero duration does not fire `animationend`.
|
|
92
|
+
*
|
|
93
|
+
* @param {HTMLElement} element
|
|
94
|
+
* @return {boolean}
|
|
95
|
+
*/
|
|
96
|
+
export function shouldAnimate(element) {
|
|
97
|
+
const style = getComputedStyle(element);
|
|
98
|
+
const name = style.getPropertyValue('animation-name');
|
|
99
|
+
const hasDuration = style
|
|
100
|
+
.getPropertyValue('animation-duration')
|
|
101
|
+
.split(',')
|
|
102
|
+
.some((duration) => parseFloat(duration) > 0);
|
|
103
|
+
return style.getPropertyValue('display') !== 'none' && name && name !== 'none' && hasDuration;
|
|
104
|
+
}
|
|
105
|
+
|
|
88
106
|
/**
|
|
89
107
|
* Toggle the state attribute on the overlay element and also its owner element. This allows targeting state attributes
|
|
90
108
|
* in the light DOM in case the overlay is in the shadow DOM of its owner.
|