@vaadin/menu-bar 25.0.0-alpha9 → 25.0.0-beta1
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 +15 -18
- package/src/styles/vaadin-menu-bar-base-styles.js +7 -6
- package/src/styles/vaadin-menu-bar-button-base-styles.js +1 -1
- package/src/vaadin-menu-bar-button.d.ts +19 -0
- package/src/vaadin-menu-bar-button.js +3 -1
- package/src/vaadin-menu-bar-item.js +1 -1
- package/src/vaadin-menu-bar-list-box.js +1 -1
- package/src/vaadin-menu-bar-mixin.d.ts +5 -12
- package/src/vaadin-menu-bar-mixin.js +20 -35
- package/src/vaadin-menu-bar-overlay.js +1 -1
- package/src/vaadin-menu-bar-submenu.d.ts +20 -0
- package/src/vaadin-menu-bar-submenu.js +69 -3
- package/src/vaadin-menu-bar.js +1 -1
- package/vaadin-menu-bar.js +1 -1
- package/web-types.json +4 -26
- package/web-types.lit.json +4 -11
- package/src/styles/vaadin-menu-bar-button-core-styles.d.ts +0 -8
- package/src/styles/vaadin-menu-bar-button-core-styles.js +0 -16
- package/src/styles/vaadin-menu-bar-core-styles.d.ts +0 -8
- package/src/styles/vaadin-menu-bar-core-styles.js +0 -24
- package/src/styles/vaadin-menu-bar-item-core-styles.d.ts +0 -8
- package/src/styles/vaadin-menu-bar-item-core-styles.js +0 -8
- package/src/styles/vaadin-menu-bar-overlay-core-styles.d.ts +0 -8
- package/src/styles/vaadin-menu-bar-overlay-core-styles.js +0 -9
- package/src/vaadin-menu-bar-submenu-mixin.js +0 -66
- package/theme/lumo/vaadin-menu-bar-button-styles.d.ts +0 -1
- package/theme/lumo/vaadin-menu-bar-button-styles.js +0 -128
- package/theme/lumo/vaadin-menu-bar-button.d.ts +0 -2
- package/theme/lumo/vaadin-menu-bar-button.js +0 -2
- package/theme/lumo/vaadin-menu-bar-item-styles.d.ts +0 -2
- package/theme/lumo/vaadin-menu-bar-item-styles.js +0 -27
- package/theme/lumo/vaadin-menu-bar-list-box-styles.d.ts +0 -1
- package/theme/lumo/vaadin-menu-bar-list-box-styles.js +0 -5
- package/theme/lumo/vaadin-menu-bar-overlay-styles.d.ts +0 -1
- package/theme/lumo/vaadin-menu-bar-overlay-styles.js +0 -13
- package/theme/lumo/vaadin-menu-bar-styles.d.ts +0 -1
- package/theme/lumo/vaadin-menu-bar-styles.js +0 -17
- package/theme/lumo/vaadin-menu-bar.d.ts +0 -6
- package/theme/lumo/vaadin-menu-bar.js +0 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/menu-bar",
|
|
3
|
-
"version": "25.0.0-
|
|
3
|
+
"version": "25.0.0-beta1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -21,9 +21,6 @@
|
|
|
21
21
|
"type": "module",
|
|
22
22
|
"files": [
|
|
23
23
|
"src",
|
|
24
|
-
"!src/styles/*-base-styles.d.ts",
|
|
25
|
-
"!src/styles/*-base-styles.js",
|
|
26
|
-
"theme",
|
|
27
24
|
"vaadin-*.d.ts",
|
|
28
25
|
"vaadin-*.js",
|
|
29
26
|
"web-types.json",
|
|
@@ -37,27 +34,27 @@
|
|
|
37
34
|
],
|
|
38
35
|
"dependencies": {
|
|
39
36
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
40
|
-
"@vaadin/a11y-base": "25.0.0-
|
|
41
|
-
"@vaadin/button": "25.0.0-
|
|
42
|
-
"@vaadin/component-base": "25.0.0-
|
|
43
|
-
"@vaadin/context-menu": "25.0.0-
|
|
44
|
-
"@vaadin/item": "25.0.0-
|
|
45
|
-
"@vaadin/list-box": "25.0.0-
|
|
46
|
-
"@vaadin/overlay": "25.0.0-
|
|
47
|
-
"@vaadin/vaadin-
|
|
48
|
-
"@vaadin/vaadin-themable-mixin": "25.0.0-alpha9",
|
|
37
|
+
"@vaadin/a11y-base": "25.0.0-beta1",
|
|
38
|
+
"@vaadin/button": "25.0.0-beta1",
|
|
39
|
+
"@vaadin/component-base": "25.0.0-beta1",
|
|
40
|
+
"@vaadin/context-menu": "25.0.0-beta1",
|
|
41
|
+
"@vaadin/item": "25.0.0-beta1",
|
|
42
|
+
"@vaadin/list-box": "25.0.0-beta1",
|
|
43
|
+
"@vaadin/overlay": "25.0.0-beta1",
|
|
44
|
+
"@vaadin/vaadin-themable-mixin": "25.0.0-beta1",
|
|
49
45
|
"lit": "^3.0.0"
|
|
50
46
|
},
|
|
51
47
|
"devDependencies": {
|
|
52
|
-
"@vaadin/chai-plugins": "25.0.0-
|
|
53
|
-
"@vaadin/icon": "25.0.0-
|
|
54
|
-
"@vaadin/test-runner-commands": "25.0.0-
|
|
48
|
+
"@vaadin/chai-plugins": "25.0.0-beta1",
|
|
49
|
+
"@vaadin/icon": "25.0.0-beta1",
|
|
50
|
+
"@vaadin/test-runner-commands": "25.0.0-beta1",
|
|
55
51
|
"@vaadin/testing-helpers": "^2.0.0",
|
|
56
|
-
"
|
|
52
|
+
"@vaadin/vaadin-lumo-styles": "25.0.0-beta1",
|
|
53
|
+
"sinon": "^21.0.0"
|
|
57
54
|
},
|
|
58
55
|
"web-types": [
|
|
59
56
|
"web-types.json",
|
|
60
57
|
"web-types.lit.json"
|
|
61
58
|
],
|
|
62
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "1d20cf54e582d1f2e209126d4586f8b4c01c50e0"
|
|
63
60
|
}
|
|
@@ -17,16 +17,15 @@ export const menuBarStyles = css`
|
|
|
17
17
|
[part='container'] {
|
|
18
18
|
display: flex;
|
|
19
19
|
flex-wrap: nowrap;
|
|
20
|
-
margin: calc((var(--vaadin-focus-ring-width) +
|
|
20
|
+
margin: calc((var(--vaadin-focus-ring-width) + 2px) * -1);
|
|
21
21
|
overflow: hidden;
|
|
22
|
-
padding: calc(var(--vaadin-focus-ring-width) +
|
|
22
|
+
padding: calc(var(--vaadin-focus-ring-width) + 2px);
|
|
23
23
|
position: relative;
|
|
24
24
|
width: 100%;
|
|
25
25
|
--_gap: var(--vaadin-menu-bar-gap, 0px);
|
|
26
26
|
--_bw: var(--vaadin-button-border-width, 1px);
|
|
27
27
|
gap: var(--_gap);
|
|
28
28
|
--_rad-button: var(--vaadin-button-border-radius, var(--vaadin-radius-m));
|
|
29
|
-
--_rad: min(var(--_gap) * 1000, var(--_rad-button));
|
|
30
29
|
}
|
|
31
30
|
|
|
32
31
|
::slotted(vaadin-menu-bar-button:not(:first-of-type)) {
|
|
@@ -34,16 +33,18 @@ export const menuBarStyles = css`
|
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
::slotted(vaadin-menu-bar-button) {
|
|
37
|
-
border-radius:
|
|
36
|
+
border-radius: 0;
|
|
38
37
|
}
|
|
39
38
|
|
|
40
39
|
::slotted([first-visible]),
|
|
41
|
-
:host([has-single-button]) ::slotted([slot='overflow'])
|
|
40
|
+
:host([has-single-button]) ::slotted([slot='overflow']),
|
|
41
|
+
::slotted(vaadin-menu-bar-button[theme~='tertiary']) {
|
|
42
42
|
border-start-start-radius: var(--_rad-button);
|
|
43
43
|
border-end-start-radius: var(--_rad-button);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
::slotted(:is([last-visible], [slot='overflow']))
|
|
46
|
+
::slotted(:is([last-visible], [slot='overflow'])),
|
|
47
|
+
::slotted(vaadin-menu-bar-button[theme~='tertiary']) {
|
|
47
48
|
border-start-end-radius: var(--_rad-button);
|
|
48
49
|
border-end-end-radius: var(--_rad-button);
|
|
49
50
|
}
|
|
@@ -32,7 +32,7 @@ export const menuBarButtonStyles = css`
|
|
|
32
32
|
background: currentColor;
|
|
33
33
|
content: '';
|
|
34
34
|
height: var(--vaadin-icon-size, 1lh);
|
|
35
|
-
mask
|
|
35
|
+
mask: var(--_vaadin-icon-chevron-down) 50% / var(--vaadin-icon-visual-size, 100%) no-repeat;
|
|
36
36
|
width: var(--vaadin-icon-size, 1lh);
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2019 - 2025 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { Button } from '@vaadin/button/src/vaadin-button.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* An element used internally by `<vaadin-menu-bar>`. Not intended to be used separately.
|
|
10
|
+
*/
|
|
11
|
+
declare class MenuBarButton extends Button {}
|
|
12
|
+
|
|
13
|
+
declare global {
|
|
14
|
+
interface HTMLElementTagNameMap {
|
|
15
|
+
'vaadin-menu-bar-button': MenuBarButton;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { MenuBarButton };
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Button } from '@vaadin/button/src/vaadin-button.js';
|
|
7
7
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
8
|
-
import { menuBarButtonStyles } from './styles/vaadin-menu-bar-button-
|
|
8
|
+
import { menuBarButtonStyles } from './styles/vaadin-menu-bar-button-base-styles.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* An element used internally by `<vaadin-menu-bar>`. Not intended to be used separately.
|
|
@@ -54,3 +54,5 @@ class MenuBarButton extends Button {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
defineCustomElement(MenuBarButton);
|
|
57
|
+
|
|
58
|
+
export { MenuBarButton };
|
|
@@ -10,7 +10,7 @@ import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
|
10
10
|
import { ItemMixin } from '@vaadin/item/src/vaadin-item-mixin.js';
|
|
11
11
|
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
12
12
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
13
|
-
import { menuBarItemStyles } from './styles/vaadin-menu-bar-item-
|
|
13
|
+
import { menuBarItemStyles } from './styles/vaadin-menu-bar-item-base-styles.js';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* An element used internally by `<vaadin-menu-bar>`. Not intended to be used separately.
|
|
@@ -8,7 +8,7 @@ import { ListMixin } from '@vaadin/a11y-base/src/list-mixin.js';
|
|
|
8
8
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
9
9
|
import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
|
|
10
10
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
11
|
-
import { listBoxStyles } from '@vaadin/list-box/src/styles/vaadin-list-box-
|
|
11
|
+
import { listBoxStyles } from '@vaadin/list-box/src/styles/vaadin-list-box-base-styles.js';
|
|
12
12
|
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
13
13
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
14
14
|
|
|
@@ -10,6 +10,7 @@ import type { KeyboardDirectionMixinClass } from '@vaadin/a11y-base/src/keyboard
|
|
|
10
10
|
import type { KeyboardMixinClass } from '@vaadin/a11y-base/src/keyboard-mixin.js';
|
|
11
11
|
import type { I18nMixinClass } from '@vaadin/component-base/src/i18n-mixin.js';
|
|
12
12
|
import type { ResizeMixinClass } from '@vaadin/component-base/src/resize-mixin.js';
|
|
13
|
+
import type { MenuBarButton } from './vaadin-menu-bar-button.js';
|
|
13
14
|
|
|
14
15
|
export type MenuBarItem<TItemData extends object = object> = {
|
|
15
16
|
/**
|
|
@@ -113,7 +114,7 @@ export declare class MenuBarMixinClass<TItem extends MenuBarItem = MenuBarItem>
|
|
|
113
114
|
* which makes disabled buttons focusable and hoverable, while still
|
|
114
115
|
* preventing them from being triggered:
|
|
115
116
|
*
|
|
116
|
-
* ```
|
|
117
|
+
* ```js
|
|
117
118
|
* // Set before any menu bar is attached to the DOM.
|
|
118
119
|
* window.Vaadin.featureFlags.accessibleDisabledButtons = true;
|
|
119
120
|
* ```
|
|
@@ -126,7 +127,7 @@ export declare class MenuBarMixinClass<TItem extends MenuBarItem = MenuBarItem>
|
|
|
126
127
|
* just the individual properties you want to change.
|
|
127
128
|
*
|
|
128
129
|
* The object has the following JSON structure and default values:
|
|
129
|
-
* ```
|
|
130
|
+
* ```js
|
|
130
131
|
* {
|
|
131
132
|
* moreOptions: 'More options'
|
|
132
133
|
* }
|
|
@@ -134,14 +135,6 @@ export declare class MenuBarMixinClass<TItem extends MenuBarItem = MenuBarItem>
|
|
|
134
135
|
*/
|
|
135
136
|
i18n: MenuBarI18n;
|
|
136
137
|
|
|
137
|
-
/**
|
|
138
|
-
* A space-delimited list of CSS class names
|
|
139
|
-
* to set on each sub-menu overlay element.
|
|
140
|
-
*
|
|
141
|
-
* @attr {string} overlay-class
|
|
142
|
-
*/
|
|
143
|
-
overlayClass: string;
|
|
144
|
-
|
|
145
138
|
/**
|
|
146
139
|
* If true, the submenu will open on hover (mouseover) instead of click.
|
|
147
140
|
* @attr {boolean} open-on-hover
|
|
@@ -167,11 +160,11 @@ export declare class MenuBarMixinClass<TItem extends MenuBarItem = MenuBarItem>
|
|
|
167
160
|
*/
|
|
168
161
|
close(): void;
|
|
169
162
|
|
|
170
|
-
protected readonly _buttons:
|
|
163
|
+
protected readonly _buttons: MenuBarButton[];
|
|
171
164
|
|
|
172
165
|
protected readonly _container: HTMLElement;
|
|
173
166
|
|
|
174
|
-
protected readonly _overflow:
|
|
167
|
+
protected readonly _overflow: MenuBarButton;
|
|
175
168
|
|
|
176
169
|
protected _hasOverflow: boolean;
|
|
177
170
|
}
|
|
@@ -76,10 +76,10 @@ export const MenuBarMixin = (superClass) =>
|
|
|
76
76
|
* @property {string} text - Text to be set as the menu button component's textContent.
|
|
77
77
|
* @property {string} tooltip - Text to be set as the menu button's tooltip.
|
|
78
78
|
* Requires a `<vaadin-tooltip slot="tooltip">` element to be added inside the `<vaadin-menu-bar>`.
|
|
79
|
-
* @property {
|
|
79
|
+
* @property {string | HTMLElement} component - The component to represent the button content.
|
|
80
80
|
* Either a tagName or an element instance. Defaults to "vaadin-menu-bar-item".
|
|
81
81
|
* @property {boolean} disabled - If true, the button is disabled and cannot be activated.
|
|
82
|
-
* @property {
|
|
82
|
+
* @property {string | string[]} theme - Theme(s) to be set as the theme attribute of the button, overriding any theme set on the menu bar.
|
|
83
83
|
* @property {SubMenuItem[]} children - Array of submenu items.
|
|
84
84
|
*/
|
|
85
85
|
|
|
@@ -87,7 +87,7 @@ export const MenuBarMixin = (superClass) =>
|
|
|
87
87
|
* @typedef SubMenuItem
|
|
88
88
|
* @type {object}
|
|
89
89
|
* @property {string} text - Text to be set as the menu item component's textContent.
|
|
90
|
-
* @property {
|
|
90
|
+
* @property {string | HTMLElement} component - The component to represent the item.
|
|
91
91
|
* Either a tagName or an element instance. Defaults to "vaadin-menu-bar-item".
|
|
92
92
|
* @property {boolean} disabled - If true, the item is disabled and cannot be selected.
|
|
93
93
|
* @property {boolean} checked - If true, the item shows a checkmark next to it.
|
|
@@ -136,12 +136,7 @@ export const MenuBarMixin = (superClass) =>
|
|
|
136
136
|
* which makes disabled buttons focusable and hoverable, while still
|
|
137
137
|
* preventing them from being triggered:
|
|
138
138
|
*
|
|
139
|
-
* ```
|
|
140
|
-
* // Set before any menu bar is attached to the DOM.
|
|
141
|
-
* window.Vaadin.featureFlags.accessibleDisabledButtons = true;
|
|
142
|
-
* ```
|
|
143
|
-
*
|
|
144
|
-
* ```
|
|
139
|
+
* ```js
|
|
145
140
|
* // Set before any menu bar is attached to the DOM.
|
|
146
141
|
* window.Vaadin.featureFlags.accessibleDisabledButtons = true;
|
|
147
142
|
* ```
|
|
@@ -154,16 +149,6 @@ export const MenuBarMixin = (superClass) =>
|
|
|
154
149
|
value: () => [],
|
|
155
150
|
},
|
|
156
151
|
|
|
157
|
-
/**
|
|
158
|
-
* A space-delimited list of CSS class names
|
|
159
|
-
* to set on each sub-menu overlay element.
|
|
160
|
-
*
|
|
161
|
-
* @attr {string} overlay-class
|
|
162
|
-
*/
|
|
163
|
-
overlayClass: {
|
|
164
|
-
type: String,
|
|
165
|
-
},
|
|
166
|
-
|
|
167
152
|
/**
|
|
168
153
|
* If true, the submenu will open on hover (mouseover) instead of click.
|
|
169
154
|
* @attr {boolean} open-on-hover
|
|
@@ -200,7 +185,7 @@ export const MenuBarMixin = (superClass) =>
|
|
|
200
185
|
* just the individual properties you want to change.
|
|
201
186
|
*
|
|
202
187
|
* The object has the following JSON structure and default values:
|
|
203
|
-
* ```
|
|
188
|
+
* ```js
|
|
204
189
|
* {
|
|
205
190
|
* moreOptions: 'More options'
|
|
206
191
|
* }
|
|
@@ -348,10 +333,6 @@ export const MenuBarMixin = (superClass) =>
|
|
|
348
333
|
this.__updateSubMenu();
|
|
349
334
|
}
|
|
350
335
|
|
|
351
|
-
if (props.has('overlayClass')) {
|
|
352
|
-
this._subMenu.overlayClass = this.overlayClass;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
336
|
if (props.has('_theme')) {
|
|
356
337
|
this._themeChanged(this._theme);
|
|
357
338
|
}
|
|
@@ -428,7 +409,7 @@ export const MenuBarMixin = (superClass) =>
|
|
|
428
409
|
__updateSubMenu() {
|
|
429
410
|
const subMenu = this._subMenu;
|
|
430
411
|
if (subMenu && subMenu.opened) {
|
|
431
|
-
const button = subMenu.
|
|
412
|
+
const button = subMenu._positionTarget;
|
|
432
413
|
|
|
433
414
|
// Close sub-menu if the corresponding button is no longer in the DOM,
|
|
434
415
|
// or if the item on it has been changed to no longer have children.
|
|
@@ -712,17 +693,18 @@ export const MenuBarMixin = (superClass) =>
|
|
|
712
693
|
* and open another one for the newly focused button.
|
|
713
694
|
*
|
|
714
695
|
* @param {Element} item
|
|
696
|
+
* @param {FocusOptions=} options
|
|
715
697
|
* @param {boolean} navigating
|
|
716
698
|
* @protected
|
|
717
699
|
* @override
|
|
718
700
|
*/
|
|
719
|
-
_focusItem(item, navigating) {
|
|
701
|
+
_focusItem(item, options, navigating) {
|
|
720
702
|
const wasExpanded = navigating && this.focused === this._expandedButton;
|
|
721
703
|
if (wasExpanded) {
|
|
722
704
|
this._close();
|
|
723
705
|
}
|
|
724
706
|
|
|
725
|
-
super._focusItem(item, navigating);
|
|
707
|
+
super._focusItem(item, options, navigating);
|
|
726
708
|
|
|
727
709
|
this._buttons.forEach((btn) => {
|
|
728
710
|
this._setTabindex(btn, btn === item);
|
|
@@ -779,7 +761,8 @@ export const MenuBarMixin = (superClass) =>
|
|
|
779
761
|
*/
|
|
780
762
|
_setFocused(focused) {
|
|
781
763
|
if (focused) {
|
|
782
|
-
const
|
|
764
|
+
const selector = this.tabNavigation ? '[focused]' : '[tabindex="0"]';
|
|
765
|
+
const target = this.querySelector(`vaadin-menu-bar-button${selector}`);
|
|
783
766
|
if (target) {
|
|
784
767
|
this._buttons.forEach((btn) => {
|
|
785
768
|
this._setTabindex(btn, btn === target);
|
|
@@ -890,11 +873,11 @@ export const MenuBarMixin = (superClass) =>
|
|
|
890
873
|
// Hide tooltip on mouseover to disabled button
|
|
891
874
|
this._hideTooltip();
|
|
892
875
|
} else if (button !== this._expandedButton) {
|
|
893
|
-
|
|
894
|
-
|
|
876
|
+
// Switch sub-menu when moving cursor over another button
|
|
877
|
+
// with children, regardless of whether openOnHover is set.
|
|
878
|
+
// If the button has no children, keep the sub-menu opened.
|
|
879
|
+
if (button.item.children && (this.openOnHover || this._subMenu.opened)) {
|
|
895
880
|
this.__openSubMenu(button, false);
|
|
896
|
-
} else if (isOpened) {
|
|
897
|
-
this._close();
|
|
898
881
|
}
|
|
899
882
|
|
|
900
883
|
if (button === this._overflow || (this.openOnHover && button.item.children)) {
|
|
@@ -963,6 +946,7 @@ export const MenuBarMixin = (superClass) =>
|
|
|
963
946
|
|
|
964
947
|
subMenu.items = items;
|
|
965
948
|
subMenu.listenOn = button;
|
|
949
|
+
subMenu._positionTarget = button;
|
|
966
950
|
const overlay = subMenu._overlayElement;
|
|
967
951
|
overlay.noVerticalOverlap = true;
|
|
968
952
|
|
|
@@ -972,7 +956,6 @@ export const MenuBarMixin = (superClass) =>
|
|
|
972
956
|
this._setExpanded(button, true);
|
|
973
957
|
|
|
974
958
|
this.style.pointerEvents = 'auto';
|
|
975
|
-
overlay.positionTarget = button;
|
|
976
959
|
|
|
977
960
|
button.dispatchEvent(
|
|
978
961
|
new CustomEvent('opensubmenu', {
|
|
@@ -990,7 +973,8 @@ export const MenuBarMixin = (superClass) =>
|
|
|
990
973
|
}
|
|
991
974
|
|
|
992
975
|
if (options.keepFocus) {
|
|
993
|
-
|
|
976
|
+
const focusOptions = { focusVisible: isKeyboardActive() };
|
|
977
|
+
this._focusItem(this._expandedButton, focusOptions, false);
|
|
994
978
|
}
|
|
995
979
|
|
|
996
980
|
// Do not focus item when open not from keyboard
|
|
@@ -1034,7 +1018,8 @@ export const MenuBarMixin = (superClass) =>
|
|
|
1034
1018
|
if (button && button.hasAttribute('expanded')) {
|
|
1035
1019
|
this._setExpanded(button, false);
|
|
1036
1020
|
if (restoreFocus) {
|
|
1037
|
-
|
|
1021
|
+
const focusOptions = { focusVisible: isKeyboardActive() };
|
|
1022
|
+
this._focusItem(button, focusOptions, false);
|
|
1038
1023
|
}
|
|
1039
1024
|
this._expandedButton = null;
|
|
1040
1025
|
}
|
|
@@ -11,7 +11,7 @@ import { MenuOverlayMixin } from '@vaadin/context-menu/src/vaadin-menu-overlay-m
|
|
|
11
11
|
import { OverlayMixin } from '@vaadin/overlay/src/vaadin-overlay-mixin.js';
|
|
12
12
|
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
13
13
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
14
|
-
import { menuBarOverlayStyles } from './styles/vaadin-menu-bar-overlay-
|
|
14
|
+
import { menuBarOverlayStyles } from './styles/vaadin-menu-bar-overlay-base-styles.js';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* An element used internally by `<vaadin-menu-bar>`. Not intended to be used separately.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2019 - 2025 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { ContextMenuMixin } from '@vaadin/context-menu/src/vaadin-context-menu-mixin.js';
|
|
7
|
+
import { ThemePropertyMixin } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* An element used internally by `<vaadin-menu-bar>`. Not intended to be used separately.
|
|
11
|
+
*/
|
|
12
|
+
declare class MenuBarSubmenu extends ContextMenuMixin(ThemePropertyMixin(HTMLElement)) {}
|
|
13
|
+
|
|
14
|
+
declare global {
|
|
15
|
+
interface HTMLElementTagNameMap {
|
|
16
|
+
'vaadin-menu-bar-submenu': MenuBarSubmenu;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { MenuBarSubmenu };
|
|
@@ -10,19 +10,19 @@ import { css, html, LitElement } from 'lit';
|
|
|
10
10
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
11
11
|
import { defineCustomElement } from '@vaadin/component-base/src/define.js';
|
|
12
12
|
import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
13
|
+
import { ContextMenuMixin } from '@vaadin/context-menu/src/vaadin-context-menu-mixin.js';
|
|
13
14
|
import { ThemePropertyMixin } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
|
|
14
|
-
import { SubMenuMixin } from './vaadin-menu-bar-submenu-mixin.js';
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* An element used internally by `<vaadin-menu-bar>`. Not intended to be used separately.
|
|
18
18
|
*
|
|
19
19
|
* @customElement
|
|
20
20
|
* @extends HTMLElement
|
|
21
|
-
* @mixes
|
|
21
|
+
* @mixes ContextMenuMixin
|
|
22
22
|
* @mixes ThemePropertyMixin
|
|
23
23
|
* @protected
|
|
24
24
|
*/
|
|
25
|
-
class MenuBarSubmenu extends
|
|
25
|
+
class MenuBarSubmenu extends ContextMenuMixin(ThemePropertyMixin(PolylitMixin(LitElement))) {
|
|
26
26
|
static get is() {
|
|
27
27
|
return 'vaadin-menu-bar-submenu';
|
|
28
28
|
}
|
|
@@ -39,6 +39,31 @@ class MenuBarSubmenu extends SubMenuMixin(ThemePropertyMixin(PolylitMixin(LitEle
|
|
|
39
39
|
`;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
static get properties() {
|
|
43
|
+
return {
|
|
44
|
+
isRoot: {
|
|
45
|
+
type: Boolean,
|
|
46
|
+
reflectToAttribute: true,
|
|
47
|
+
sync: true,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
constructor() {
|
|
53
|
+
super();
|
|
54
|
+
|
|
55
|
+
this.openOn = 'opensubmenu';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Tag name prefix used by overlay, list-box and items.
|
|
60
|
+
* @protected
|
|
61
|
+
* @return {string}
|
|
62
|
+
*/
|
|
63
|
+
get _tagNamePrefix() {
|
|
64
|
+
return 'vaadin-menu-bar';
|
|
65
|
+
}
|
|
66
|
+
|
|
42
67
|
/** @protected */
|
|
43
68
|
render() {
|
|
44
69
|
return html`
|
|
@@ -50,6 +75,8 @@ class MenuBarSubmenu extends SubMenuMixin(ThemePropertyMixin(PolylitMixin(LitEle
|
|
|
50
75
|
.modeless="${this._modeless}"
|
|
51
76
|
.renderer="${this.__itemsRenderer}"
|
|
52
77
|
.withBackdrop="${this._phone}"
|
|
78
|
+
.positionTarget="${this._positionTarget}"
|
|
79
|
+
?no-horizontal-overlap="${!this.isRoot}"
|
|
53
80
|
?phone="${this._phone}"
|
|
54
81
|
theme="${ifDefined(this._theme)}"
|
|
55
82
|
exportparts="backdrop, overlay, content"
|
|
@@ -61,6 +88,45 @@ class MenuBarSubmenu extends SubMenuMixin(ThemePropertyMixin(PolylitMixin(LitEle
|
|
|
61
88
|
</vaadin-menu-bar-overlay>
|
|
62
89
|
`;
|
|
63
90
|
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Overriding the observer to not add global "contextmenu" listener.
|
|
94
|
+
* @override
|
|
95
|
+
*/
|
|
96
|
+
_openedChanged() {
|
|
97
|
+
// Do nothing
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Overriding the public method to reset expanded button state.
|
|
102
|
+
*/
|
|
103
|
+
close() {
|
|
104
|
+
super.close();
|
|
105
|
+
|
|
106
|
+
// Only handle 1st level submenu
|
|
107
|
+
if (this.hasAttribute('is-root')) {
|
|
108
|
+
this.parentElement._close();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Override method from `ContextMenuMixin` to prevent closing
|
|
114
|
+
* sub-menu on the same click event that was used to open it.
|
|
115
|
+
*
|
|
116
|
+
* @param {Event} event
|
|
117
|
+
* @return {boolean}
|
|
118
|
+
* @protected
|
|
119
|
+
* @override
|
|
120
|
+
*/
|
|
121
|
+
_shouldCloseOnOutsideClick(event) {
|
|
122
|
+
if (this.hasAttribute('is-root') && event.composedPath().includes(this.listenOn)) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return super._shouldCloseOnOutsideClick(event);
|
|
127
|
+
}
|
|
64
128
|
}
|
|
65
129
|
|
|
66
130
|
defineCustomElement(MenuBarSubmenu);
|
|
131
|
+
|
|
132
|
+
export { MenuBarSubmenu };
|
package/src/vaadin-menu-bar.js
CHANGED
|
@@ -12,7 +12,7 @@ import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
|
|
|
12
12
|
import { TooltipController } from '@vaadin/component-base/src/tooltip-controller.js';
|
|
13
13
|
import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
|
|
14
14
|
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
15
|
-
import { menuBarStyles } from './styles/vaadin-menu-bar-
|
|
15
|
+
import { menuBarStyles } from './styles/vaadin-menu-bar-base-styles.js';
|
|
16
16
|
import { MenuBarMixin } from './vaadin-menu-bar-mixin.js';
|
|
17
17
|
|
|
18
18
|
/**
|
package/vaadin-menu-bar.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import './
|
|
1
|
+
import './src/vaadin-menu-bar.js';
|
|
2
2
|
export * from './src/vaadin-menu-bar.js';
|
package/web-types.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/menu-bar",
|
|
4
|
-
"version": "25.0.0-
|
|
4
|
+
"version": "25.0.0-beta1",
|
|
5
5
|
"description-markup": "markdown",
|
|
6
6
|
"contributions": {
|
|
7
7
|
"html": {
|
|
8
8
|
"elements": [
|
|
9
9
|
{
|
|
10
10
|
"name": "vaadin-menu-bar",
|
|
11
|
-
"description": "`<vaadin-menu-bar>` is a Web Component providing a set of horizontally stacked buttons offering\nthe user quick access to a consistent set of commands. Each button can toggle a submenu with\nsupport for additional levels of nested menus.\n\nTo create the menu bar, first add the component to the page:\n\n```html\n<vaadin-menu-bar></vaadin-menu-bar>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-
|
|
11
|
+
"description": "`<vaadin-menu-bar>` is a Web Component providing a set of horizontally stacked buttons offering\nthe user quick access to a consistent set of commands. Each button can toggle a submenu with\nsupport for additional levels of nested menus.\n\nTo create the menu bar, first add the component to the page:\n\n```html\n<vaadin-menu-bar></vaadin-menu-bar>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-beta1/#/elements/vaadin-menu-bar#property-items) property to initialize the structure:\n\n```js\ndocument.querySelector('vaadin-menu-bar').items = [{text: 'File'}, {text: 'Edit'}];\n```\n\n### Styling\n\nThe following shadow DOM parts are exposed for styling:\n\nPart name | Description\n------------------|----------------\n`container` | The container wrapping menu bar buttons.\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n--------------------|----------------------------------\n`disabled` | Set when the menu bar is disabled\n`has-single-button` | Set when there is only one button visible\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nIn addition to `<vaadin-menu-bar>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-menu-bar-button>` - has the same API as [`<vaadin-button>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-beta1/#/elements/vaadin-button).\n- `<vaadin-menu-bar-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-beta1/#/elements/vaadin-item).\n- `<vaadin-menu-bar-list-box>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-beta1/#/elements/vaadin-list-box).\n- `<vaadin-menu-bar-submenu>` - has the same API as [`<vaadin-context-menu>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-beta1/#/elements/vaadin-context-menu).\n\nThe `<vaadin-menu-bar-item>` sub-menu elements have the following additional state attributes\non top of the built-in `<vaadin-item>` state attributes:\n\nAttribute | Description\n---------- |-------------\n`expanded` | Expanded parent item.",
|
|
12
12
|
"attributes": [
|
|
13
13
|
{
|
|
14
14
|
"name": "disabled",
|
|
@@ -30,17 +30,6 @@
|
|
|
30
30
|
]
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
|
-
{
|
|
34
|
-
"name": "overlay-class",
|
|
35
|
-
"description": "A space-delimited list of CSS class names\nto set on each sub-menu overlay element.",
|
|
36
|
-
"value": {
|
|
37
|
-
"type": [
|
|
38
|
-
"string",
|
|
39
|
-
"null",
|
|
40
|
-
"undefined"
|
|
41
|
-
]
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
33
|
{
|
|
45
34
|
"name": "open-on-hover",
|
|
46
35
|
"description": "If true, the submenu will open on hover (mouseover) instead of click.",
|
|
@@ -101,7 +90,7 @@
|
|
|
101
90
|
},
|
|
102
91
|
{
|
|
103
92
|
"name": "i18n",
|
|
104
|
-
"description": "The object used to localize this component. To change the default\nlocalization, replace this with an object that provides all properties, or\njust the individual properties you want to change.\n\nThe object has the following JSON structure and default values:\n
|
|
93
|
+
"description": "The object used to localize this component. To change the default\nlocalization, replace this with an object that provides all properties, or\njust the individual properties you want to change.\n\nThe object has the following JSON structure and default values:\n```js\n{\n moreOptions: 'More options'\n}\n```",
|
|
105
94
|
"value": {
|
|
106
95
|
"type": [
|
|
107
96
|
"MenuBarI18n"
|
|
@@ -110,24 +99,13 @@
|
|
|
110
99
|
},
|
|
111
100
|
{
|
|
112
101
|
"name": "items",
|
|
113
|
-
"description": "Defines a hierarchical structure, where root level items represent menu bar buttons,\nand `children` property configures a submenu with items to be opened below\nthe button on click, Enter, Space, Up and Down arrow keys.\n\n#### Example\n\n```js\nmenubar.items = [\n {\n text: 'File',\n className: 'file',\n children: [\n {text: 'Open', className: 'file open'}\n {text: 'Auto Save', checked: true},\n ]\n },\n {component: 'hr'},\n {\n text: 'Edit',\n children: [\n {text: 'Undo', disabled: true},\n {text: 'Redo'}\n ]\n },\n {text: 'Help'}\n];\n```\n\n#### Disabled buttons\n\nWhen disabled, menu bar buttons (root-level items) are rendered\nas \"dimmed\" and prevent all user interactions (mouse and keyboard).\n\nSince disabled buttons are not focusable and cannot react to hover\nevents by default, it can cause accessibility issues by making them\nentirely invisible to assistive technologies, and prevents the use\nof Tooltips to explain why the action is not available. This can be\naddressed by enabling the feature flag `accessibleDisabledButtons`,\nwhich makes disabled buttons focusable and hoverable, while still\npreventing them from being triggered:\n\n
|
|
102
|
+
"description": "Defines a hierarchical structure, where root level items represent menu bar buttons,\nand `children` property configures a submenu with items to be opened below\nthe button on click, Enter, Space, Up and Down arrow keys.\n\n#### Example\n\n```js\nmenubar.items = [\n {\n text: 'File',\n className: 'file',\n children: [\n {text: 'Open', className: 'file open'}\n {text: 'Auto Save', checked: true},\n ]\n },\n {component: 'hr'},\n {\n text: 'Edit',\n children: [\n {text: 'Undo', disabled: true},\n {text: 'Redo'}\n ]\n },\n {text: 'Help'}\n];\n```\n\n#### Disabled buttons\n\nWhen disabled, menu bar buttons (root-level items) are rendered\nas \"dimmed\" and prevent all user interactions (mouse and keyboard).\n\nSince disabled buttons are not focusable and cannot react to hover\nevents by default, it can cause accessibility issues by making them\nentirely invisible to assistive technologies, and prevents the use\nof Tooltips to explain why the action is not available. This can be\naddressed by enabling the feature flag `accessibleDisabledButtons`,\nwhich makes disabled buttons focusable and hoverable, while still\npreventing them from being triggered:\n\n```js\n// Set before any menu bar is attached to the DOM.\nwindow.Vaadin.featureFlags.accessibleDisabledButtons = true;\n```",
|
|
114
103
|
"value": {
|
|
115
104
|
"type": [
|
|
116
105
|
"Array.<MenuBarItem>"
|
|
117
106
|
]
|
|
118
107
|
}
|
|
119
108
|
},
|
|
120
|
-
{
|
|
121
|
-
"name": "overlayClass",
|
|
122
|
-
"description": "A space-delimited list of CSS class names\nto set on each sub-menu overlay element.",
|
|
123
|
-
"value": {
|
|
124
|
-
"type": [
|
|
125
|
-
"string",
|
|
126
|
-
"null",
|
|
127
|
-
"undefined"
|
|
128
|
-
]
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
109
|
{
|
|
132
110
|
"name": "openOnHover",
|
|
133
111
|
"description": "If true, the submenu will open on hover (mouseover) instead of click.",
|
package/web-types.lit.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/web-types",
|
|
3
3
|
"name": "@vaadin/menu-bar",
|
|
4
|
-
"version": "25.0.0-
|
|
4
|
+
"version": "25.0.0-beta1",
|
|
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-menu-bar",
|
|
19
|
-
"description": "`<vaadin-menu-bar>` is a Web Component providing a set of horizontally stacked buttons offering\nthe user quick access to a consistent set of commands. Each button can toggle a submenu with\nsupport for additional levels of nested menus.\n\nTo create the menu bar, first add the component to the page:\n\n```html\n<vaadin-menu-bar></vaadin-menu-bar>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-
|
|
19
|
+
"description": "`<vaadin-menu-bar>` is a Web Component providing a set of horizontally stacked buttons offering\nthe user quick access to a consistent set of commands. Each button can toggle a submenu with\nsupport for additional levels of nested menus.\n\nTo create the menu bar, first add the component to the page:\n\n```html\n<vaadin-menu-bar></vaadin-menu-bar>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-beta1/#/elements/vaadin-menu-bar#property-items) property to initialize the structure:\n\n```js\ndocument.querySelector('vaadin-menu-bar').items = [{text: 'File'}, {text: 'Edit'}];\n```\n\n### Styling\n\nThe following shadow DOM parts are exposed for styling:\n\nPart name | Description\n------------------|----------------\n`container` | The container wrapping menu bar buttons.\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n--------------------|----------------------------------\n`disabled` | Set when the menu bar is disabled\n`has-single-button` | Set when there is only one button visible\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.\n\n### Internal components\n\nIn addition to `<vaadin-menu-bar>` itself, the following internal\ncomponents are themable:\n\n- `<vaadin-menu-bar-button>` - has the same API as [`<vaadin-button>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-beta1/#/elements/vaadin-button).\n- `<vaadin-menu-bar-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-beta1/#/elements/vaadin-item).\n- `<vaadin-menu-bar-list-box>` - has the same API as [`<vaadin-list-box>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-beta1/#/elements/vaadin-list-box).\n- `<vaadin-menu-bar-submenu>` - has the same API as [`<vaadin-context-menu>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-beta1/#/elements/vaadin-context-menu).\n\nThe `<vaadin-menu-bar-item>` sub-menu elements have the following additional state attributes\non top of the built-in `<vaadin-item>` state attributes:\n\nAttribute | Description\n---------- |-------------\n`expanded` | Expanded parent item.",
|
|
20
20
|
"extension": true,
|
|
21
21
|
"attributes": [
|
|
22
22
|
{
|
|
@@ -49,21 +49,14 @@
|
|
|
49
49
|
},
|
|
50
50
|
{
|
|
51
51
|
"name": ".i18n",
|
|
52
|
-
"description": "The object used to localize this component. To change the default\nlocalization, replace this with an object that provides all properties, or\njust the individual properties you want to change.\n\nThe object has the following JSON structure and default values:\n
|
|
52
|
+
"description": "The object used to localize this component. To change the default\nlocalization, replace this with an object that provides all properties, or\njust the individual properties you want to change.\n\nThe object has the following JSON structure and default values:\n```js\n{\n moreOptions: 'More options'\n}\n```",
|
|
53
53
|
"value": {
|
|
54
54
|
"kind": "expression"
|
|
55
55
|
}
|
|
56
56
|
},
|
|
57
57
|
{
|
|
58
58
|
"name": ".items",
|
|
59
|
-
"description": "Defines a hierarchical structure, where root level items represent menu bar buttons,\nand `children` property configures a submenu with items to be opened below\nthe button on click, Enter, Space, Up and Down arrow keys.\n\n#### Example\n\n```js\nmenubar.items = [\n {\n text: 'File',\n className: 'file',\n children: [\n {text: 'Open', className: 'file open'}\n {text: 'Auto Save', checked: true},\n ]\n },\n {component: 'hr'},\n {\n text: 'Edit',\n children: [\n {text: 'Undo', disabled: true},\n {text: 'Redo'}\n ]\n },\n {text: 'Help'}\n];\n```\n\n#### Disabled buttons\n\nWhen disabled, menu bar buttons (root-level items) are rendered\nas \"dimmed\" and prevent all user interactions (mouse and keyboard).\n\nSince disabled buttons are not focusable and cannot react to hover\nevents by default, it can cause accessibility issues by making them\nentirely invisible to assistive technologies, and prevents the use\nof Tooltips to explain why the action is not available. This can be\naddressed by enabling the feature flag `accessibleDisabledButtons`,\nwhich makes disabled buttons focusable and hoverable, while still\npreventing them from being triggered:\n\n
|
|
60
|
-
"value": {
|
|
61
|
-
"kind": "expression"
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
"name": ".overlayClass",
|
|
66
|
-
"description": "A space-delimited list of CSS class names\nto set on each sub-menu overlay element.",
|
|
59
|
+
"description": "Defines a hierarchical structure, where root level items represent menu bar buttons,\nand `children` property configures a submenu with items to be opened below\nthe button on click, Enter, Space, Up and Down arrow keys.\n\n#### Example\n\n```js\nmenubar.items = [\n {\n text: 'File',\n className: 'file',\n children: [\n {text: 'Open', className: 'file open'}\n {text: 'Auto Save', checked: true},\n ]\n },\n {component: 'hr'},\n {\n text: 'Edit',\n children: [\n {text: 'Undo', disabled: true},\n {text: 'Redo'}\n ]\n },\n {text: 'Help'}\n];\n```\n\n#### Disabled buttons\n\nWhen disabled, menu bar buttons (root-level items) are rendered\nas \"dimmed\" and prevent all user interactions (mouse and keyboard).\n\nSince disabled buttons are not focusable and cannot react to hover\nevents by default, it can cause accessibility issues by making them\nentirely invisible to assistive technologies, and prevents the use\nof Tooltips to explain why the action is not available. This can be\naddressed by enabling the feature flag `accessibleDisabledButtons`,\nwhich makes disabled buttons focusable and hoverable, while still\npreventing them from being triggered:\n\n```js\n// Set before any menu bar is attached to the DOM.\nwindow.Vaadin.featureFlags.accessibleDisabledButtons = true;\n```",
|
|
67
60
|
"value": {
|
|
68
61
|
"kind": "expression"
|
|
69
62
|
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2019 - 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
|
-
|
|
8
|
-
export const menuBarButtonStyles = css`
|
|
9
|
-
:host {
|
|
10
|
-
flex-shrink: 0;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
:host([slot='overflow']) {
|
|
14
|
-
margin-inline-end: 0;
|
|
15
|
-
}
|
|
16
|
-
`;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2019 - 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
|
-
|
|
8
|
-
export const menuBarStyles = css`
|
|
9
|
-
:host {
|
|
10
|
-
display: block;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
:host([hidden]) {
|
|
14
|
-
display: none !important;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
[part='container'] {
|
|
18
|
-
position: relative;
|
|
19
|
-
display: flex;
|
|
20
|
-
width: 100%;
|
|
21
|
-
flex-wrap: nowrap;
|
|
22
|
-
overflow: hidden;
|
|
23
|
-
}
|
|
24
|
-
`;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2019 - 2025 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import { itemStyles } from '@vaadin/item/src/styles/vaadin-item-core-styles.js';
|
|
7
|
-
|
|
8
|
-
export const menuBarItemStyles = [itemStyles];
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2019 - 2025 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import { menuOverlayStyles } from '@vaadin/context-menu/src/styles/vaadin-menu-overlay-core-styles.js';
|
|
7
|
-
import { overlayStyles } from '@vaadin/overlay/src/styles/vaadin-overlay-core-styles.js';
|
|
8
|
-
|
|
9
|
-
export const menuBarOverlayStyles = [overlayStyles, menuOverlayStyles];
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright (c) 2019 - 2025 Vaadin Ltd.
|
|
4
|
-
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
-
*/
|
|
6
|
-
import { OverlayClassMixin } from '@vaadin/component-base/src/overlay-class-mixin.js';
|
|
7
|
-
import { ContextMenuMixin } from '@vaadin/context-menu/src/vaadin-context-menu-mixin.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @polymerMixin
|
|
11
|
-
* @mixes ContextMenuMixin
|
|
12
|
-
* @mixes OverlayClassMixin
|
|
13
|
-
*/
|
|
14
|
-
export const SubMenuMixin = (superClass) =>
|
|
15
|
-
class SubMenuMixinClass extends ContextMenuMixin(OverlayClassMixin(superClass)) {
|
|
16
|
-
constructor() {
|
|
17
|
-
super();
|
|
18
|
-
|
|
19
|
-
this.openOn = 'opensubmenu';
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Tag name prefix used by overlay, list-box and items.
|
|
24
|
-
* @protected
|
|
25
|
-
* @return {string}
|
|
26
|
-
*/
|
|
27
|
-
get _tagNamePrefix() {
|
|
28
|
-
return 'vaadin-menu-bar';
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Overriding the observer to not add global "contextmenu" listener.
|
|
33
|
-
*/
|
|
34
|
-
_openedChanged() {
|
|
35
|
-
// Do nothing
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Overriding the public method to reset expanded button state.
|
|
40
|
-
*/
|
|
41
|
-
close() {
|
|
42
|
-
super.close();
|
|
43
|
-
|
|
44
|
-
// Only handle 1st level submenu
|
|
45
|
-
if (this.hasAttribute('is-root')) {
|
|
46
|
-
this.parentElement._close();
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Override method from `ContextMenuMixin` to prevent closing
|
|
52
|
-
* sub-menu on the same click event that was used to open it.
|
|
53
|
-
*
|
|
54
|
-
* @param {Event} event
|
|
55
|
-
* @return {boolean}
|
|
56
|
-
* @protected
|
|
57
|
-
* @override
|
|
58
|
-
*/
|
|
59
|
-
_shouldCloseOnOutsideClick(event) {
|
|
60
|
-
if (this.hasAttribute('is-root') && event.composedPath().includes(this.listenOn)) {
|
|
61
|
-
return false;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return super._shouldCloseOnOutsideClick(event);
|
|
65
|
-
}
|
|
66
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { button } from '@vaadin/button/theme/lumo/vaadin-button-styles.js';
|
|
2
|
-
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
3
|
-
|
|
4
|
-
const menuBarButton = css`
|
|
5
|
-
:host {
|
|
6
|
-
margin: calc(var(--lumo-space-xs) / 2);
|
|
7
|
-
margin-left: 0;
|
|
8
|
-
border-radius: 0;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
[part='label'] {
|
|
12
|
-
width: 100%;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/* NOTE(web-padawan): avoid using shorthand padding property for IE11 */
|
|
16
|
-
[part='label'] ::slotted(vaadin-menu-bar-item) {
|
|
17
|
-
justify-content: center;
|
|
18
|
-
background-color: transparent;
|
|
19
|
-
height: var(--lumo-button-size);
|
|
20
|
-
margin: 0 calc((var(--lumo-size-m) / 3 + var(--lumo-border-radius-m) / 2) * -1);
|
|
21
|
-
padding-left: calc(var(--lumo-size-m) / 3 + var(--lumo-border-radius-m) / 2);
|
|
22
|
-
padding-right: calc(var(--lumo-size-m) / 3 + var(--lumo-border-radius-m) / 2);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
:host([theme~='small']) [part='label'] ::slotted(vaadin-menu-bar-item) {
|
|
26
|
-
min-height: var(--lumo-size-s);
|
|
27
|
-
margin: 0 calc((var(--lumo-size-s) / 3 + var(--lumo-border-radius-m) / 2) * -1);
|
|
28
|
-
padding-left: calc(var(--lumo-size-s) / 3 + var(--lumo-border-radius-m) / 2);
|
|
29
|
-
padding-right: calc(var(--lumo-size-s) / 3 + var(--lumo-border-radius-m) / 2);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
:host([theme~='tertiary']) [part='label'] ::slotted(vaadin-menu-bar-item) {
|
|
33
|
-
margin: 0 calc((var(--lumo-button-size) / 6) * -1);
|
|
34
|
-
padding-left: calc(var(--lumo-button-size) / 6);
|
|
35
|
-
padding-right: calc(var(--lumo-button-size) / 6);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
:host([theme~='tertiary-inline']) {
|
|
39
|
-
margin-top: calc(var(--lumo-space-xs) / 2);
|
|
40
|
-
margin-bottom: calc(var(--lumo-space-xs) / 2);
|
|
41
|
-
margin-right: calc(var(--lumo-space-xs) / 2);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
:host([theme~='tertiary-inline']) [part='label'] ::slotted(vaadin-menu-bar-item) {
|
|
45
|
-
margin: 0;
|
|
46
|
-
padding: 0;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
:host([first-visible]) {
|
|
50
|
-
border-radius: var(--lumo-border-radius-m) 0 0 var(--lumo-border-radius-m);
|
|
51
|
-
|
|
52
|
-
/* Needed to retain the focus-ring with border-radius */
|
|
53
|
-
margin-left: calc(var(--lumo-space-xs) / 2);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
:host([last-visible]),
|
|
57
|
-
:host([slot='overflow']) {
|
|
58
|
-
border-radius: 0 var(--lumo-border-radius-m) var(--lumo-border-radius-m) 0;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
:host([theme~='tertiary']),
|
|
62
|
-
:host([theme~='tertiary-inline']) {
|
|
63
|
-
border-radius: var(--lumo-border-radius-m);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
:host([slot='overflow']) {
|
|
67
|
-
min-width: var(--lumo-button-size);
|
|
68
|
-
padding-left: calc(var(--lumo-button-size) / 4);
|
|
69
|
-
padding-right: calc(var(--lumo-button-size) / 4);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
:host([slot='overflow']) ::slotted(*) {
|
|
73
|
-
font-size: var(--lumo-font-size-xl);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
:host([slot='overflow']) [part='prefix'],
|
|
77
|
-
:host([slot='overflow']) [part='suffix'] {
|
|
78
|
-
margin-left: 0;
|
|
79
|
-
margin-right: 0;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
:host([theme~='dropdown-indicators']:not([slot='overflow']):not([theme~='icon'])[aria-haspopup]) [part='suffix'] {
|
|
83
|
-
margin-inline-start: 0;
|
|
84
|
-
width: 1em;
|
|
85
|
-
height: 1em;
|
|
86
|
-
line-height: 1;
|
|
87
|
-
font-size: var(--lumo-icon-size-s);
|
|
88
|
-
position: relative;
|
|
89
|
-
inset-inline-start: 0.15em;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/* prettier-ignore */
|
|
93
|
-
:host([theme~='dropdown-indicators']:not([slot='overflow']):not([theme~='icon'])[aria-haspopup]) [part='suffix']::after {
|
|
94
|
-
font-family: lumo-icons;
|
|
95
|
-
content: var(--lumo-icons-dropdown);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/* prettier-ignore */
|
|
99
|
-
:host([theme~='dropdown-indicators']:not([slot='overflow']):not([theme~='icon'])[theme~='tertiary'][aria-haspopup]) [part='suffix'] {
|
|
100
|
-
inset-inline-start: 0.05em;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/* prettier-ignore */
|
|
104
|
-
:host([theme~='dropdown-indicators']:not([slot='overflow']):not([theme~='icon'])[theme~='tertiary-inline'][aria-haspopup]) [part='suffix'] {
|
|
105
|
-
inset-inline-start: 0;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/* RTL styles */
|
|
109
|
-
:host([dir='rtl']) {
|
|
110
|
-
margin-left: calc(var(--lumo-space-xs) / 2);
|
|
111
|
-
margin-right: 0;
|
|
112
|
-
border-radius: 0;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
:host([dir='rtl'][first-visible]) {
|
|
116
|
-
border-radius: 0 var(--lumo-border-radius-m) var(--lumo-border-radius-m) 0;
|
|
117
|
-
margin-right: calc(var(--lumo-space-xs) / 2);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
:host([dir='rtl'][last-visible]),
|
|
121
|
-
:host([dir='rtl'][slot='overflow']) {
|
|
122
|
-
border-radius: var(--lumo-border-radius-m) 0 0 var(--lumo-border-radius-m);
|
|
123
|
-
}
|
|
124
|
-
`;
|
|
125
|
-
|
|
126
|
-
registerStyles('vaadin-menu-bar-button', [button, menuBarButton], {
|
|
127
|
-
moduleId: 'lumo-menu-bar-button',
|
|
128
|
-
});
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import '@vaadin/vaadin-lumo-styles/sizing.js';
|
|
2
|
-
import '@vaadin/vaadin-lumo-styles/spacing.js';
|
|
3
|
-
import { contextMenuItem } from '@vaadin/context-menu/theme/lumo/vaadin-context-menu-item-styles.js';
|
|
4
|
-
import { item } from '@vaadin/item/theme/lumo/vaadin-item-styles.js';
|
|
5
|
-
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
6
|
-
|
|
7
|
-
const menuBarItem = css`
|
|
8
|
-
[part='content'] {
|
|
9
|
-
display: flex;
|
|
10
|
-
/* tweak to inherit centering from menu bar button */
|
|
11
|
-
align-items: inherit;
|
|
12
|
-
justify-content: inherit;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
[part='content'] ::slotted(vaadin-icon) {
|
|
16
|
-
display: inline-block;
|
|
17
|
-
width: var(--lumo-icon-size-m);
|
|
18
|
-
height: var(--lumo-icon-size-m);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
[part='content'] ::slotted(vaadin-icon[icon^='vaadin:']) {
|
|
22
|
-
padding: var(--lumo-space-xs);
|
|
23
|
-
box-sizing: border-box !important;
|
|
24
|
-
}
|
|
25
|
-
`;
|
|
26
|
-
|
|
27
|
-
registerStyles('vaadin-menu-bar-item', [item, contextMenuItem, menuBarItem], { moduleId: 'lumo-menu-bar-item' });
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { contextMenuListBox } from '@vaadin/context-menu/theme/lumo/vaadin-context-menu-list-box-styles.js';
|
|
2
|
-
import { listBox } from '@vaadin/list-box/theme/lumo/vaadin-list-box-styles.js';
|
|
3
|
-
import { registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
4
|
-
|
|
5
|
-
registerStyles('vaadin-menu-bar-list-box', [listBox, contextMenuListBox], { moduleId: 'lumo-menu-bar-list-box' });
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { contextMenuOverlay } from '@vaadin/context-menu/theme/lumo/vaadin-context-menu-overlay-styles.js';
|
|
2
|
-
import { menuOverlay } from '@vaadin/vaadin-lumo-styles/mixins/menu-overlay.js';
|
|
3
|
-
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
4
|
-
|
|
5
|
-
const menuBarOverlay = css`
|
|
6
|
-
:host(:first-of-type) {
|
|
7
|
-
padding-top: var(--lumo-space-xs);
|
|
8
|
-
}
|
|
9
|
-
`;
|
|
10
|
-
|
|
11
|
-
registerStyles('vaadin-menu-bar-overlay', [menuOverlay, contextMenuOverlay, menuBarOverlay], {
|
|
12
|
-
moduleId: 'lumo-menu-bar-overlay',
|
|
13
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import '@vaadin/vaadin-lumo-styles/style.js';
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import '@vaadin/vaadin-lumo-styles/style.js';
|
|
2
|
-
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
|
|
3
|
-
|
|
4
|
-
registerStyles(
|
|
5
|
-
'vaadin-menu-bar',
|
|
6
|
-
css`
|
|
7
|
-
:host([has-single-button]) ::slotted(vaadin-menu-bar-button) {
|
|
8
|
-
border-radius: var(--lumo-border-radius-m);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
:host([theme~='end-aligned']) ::slotted(vaadin-menu-bar-button[first-visible]),
|
|
12
|
-
:host([theme~='end-aligned'][has-single-button]) ::slotted(vaadin-menu-bar-button) {
|
|
13
|
-
margin-inline-start: auto;
|
|
14
|
-
}
|
|
15
|
-
`,
|
|
16
|
-
{ moduleId: 'lumo-menu-bar' },
|
|
17
|
-
);
|