@vaadin/menu-bar 24.8.0-alpha9 → 24.8.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 -15
- package/src/vaadin-menu-bar-mixin.js +142 -150
- package/web-types.json +2 -2
- package/web-types.lit.json +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/menu-bar",
|
|
3
|
-
"version": "24.8.0-
|
|
3
|
+
"version": "24.8.0-beta1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -37,22 +37,22 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
39
39
|
"@polymer/polymer": "^3.0.0",
|
|
40
|
-
"@vaadin/a11y-base": "24.8.0-
|
|
41
|
-
"@vaadin/button": "24.8.0-
|
|
42
|
-
"@vaadin/component-base": "24.8.0-
|
|
43
|
-
"@vaadin/context-menu": "24.8.0-
|
|
44
|
-
"@vaadin/item": "24.8.0-
|
|
45
|
-
"@vaadin/list-box": "24.8.0-
|
|
46
|
-
"@vaadin/overlay": "24.8.0-
|
|
47
|
-
"@vaadin/vaadin-lumo-styles": "24.8.0-
|
|
48
|
-
"@vaadin/vaadin-material-styles": "24.8.0-
|
|
49
|
-
"@vaadin/vaadin-themable-mixin": "24.8.0-
|
|
40
|
+
"@vaadin/a11y-base": "24.8.0-beta1",
|
|
41
|
+
"@vaadin/button": "24.8.0-beta1",
|
|
42
|
+
"@vaadin/component-base": "24.8.0-beta1",
|
|
43
|
+
"@vaadin/context-menu": "24.8.0-beta1",
|
|
44
|
+
"@vaadin/item": "24.8.0-beta1",
|
|
45
|
+
"@vaadin/list-box": "24.8.0-beta1",
|
|
46
|
+
"@vaadin/overlay": "24.8.0-beta1",
|
|
47
|
+
"@vaadin/vaadin-lumo-styles": "24.8.0-beta1",
|
|
48
|
+
"@vaadin/vaadin-material-styles": "24.8.0-beta1",
|
|
49
|
+
"@vaadin/vaadin-themable-mixin": "24.8.0-beta1",
|
|
50
50
|
"lit": "^3.0.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@vaadin/chai-plugins": "24.8.0-
|
|
54
|
-
"@vaadin/icon": "24.8.0-
|
|
55
|
-
"@vaadin/test-runner-commands": "24.8.0-
|
|
53
|
+
"@vaadin/chai-plugins": "24.8.0-beta1",
|
|
54
|
+
"@vaadin/icon": "24.8.0-beta1",
|
|
55
|
+
"@vaadin/test-runner-commands": "24.8.0-beta1",
|
|
56
56
|
"@vaadin/testing-helpers": "^1.1.0",
|
|
57
57
|
"sinon": "^18.0.0"
|
|
58
58
|
},
|
|
@@ -60,5 +60,5 @@
|
|
|
60
60
|
"web-types.json",
|
|
61
61
|
"web-types.lit.json"
|
|
62
62
|
],
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "57ce3a90de99e49049312b0ba4041d3e7542e9d8"
|
|
64
64
|
}
|
|
@@ -3,15 +3,53 @@
|
|
|
3
3
|
* Copyright (c) 2019 - 2025 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
+
import { html, noChange, nothing, render } from 'lit';
|
|
7
|
+
import { Directive, directive } from 'lit/directive.js';
|
|
8
|
+
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
6
9
|
import { DisabledMixin } from '@vaadin/a11y-base/src/disabled-mixin.js';
|
|
7
10
|
import { FocusMixin } from '@vaadin/a11y-base/src/focus-mixin.js';
|
|
8
|
-
import { isElementFocused,
|
|
11
|
+
import { isElementFocused, isKeyboardActive } from '@vaadin/a11y-base/src/focus-utils.js';
|
|
9
12
|
import { KeyboardDirectionMixin } from '@vaadin/a11y-base/src/keyboard-direction-mixin.js';
|
|
10
13
|
import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
|
|
11
14
|
import { I18nMixin } from '@vaadin/component-base/src/i18n-mixin.js';
|
|
12
15
|
import { ResizeMixin } from '@vaadin/component-base/src/resize-mixin.js';
|
|
13
16
|
import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
|
|
14
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Custom Lit directive for rendering item components
|
|
20
|
+
* inspired by the `flowComponentDirective` logic.
|
|
21
|
+
*/
|
|
22
|
+
class ItemComponentDirective extends Directive {
|
|
23
|
+
update(part, [{ component, text }]) {
|
|
24
|
+
const { parentNode, startNode } = part;
|
|
25
|
+
|
|
26
|
+
const newNode = component || (text ? document.createTextNode(text) : null);
|
|
27
|
+
const oldNode = this.getOldNode(part);
|
|
28
|
+
|
|
29
|
+
if (oldNode === newNode) {
|
|
30
|
+
return noChange;
|
|
31
|
+
} else if (oldNode && newNode) {
|
|
32
|
+
parentNode.replaceChild(newNode, oldNode);
|
|
33
|
+
} else if (oldNode) {
|
|
34
|
+
parentNode.removeChild(oldNode);
|
|
35
|
+
} else if (newNode) {
|
|
36
|
+
startNode.after(newNode);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return noChange;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
getOldNode(part) {
|
|
43
|
+
const { startNode, endNode } = part;
|
|
44
|
+
if (startNode.nextSibling === endNode) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
return startNode.nextSibling;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const componentDirective = directive(ItemComponentDirective);
|
|
52
|
+
|
|
15
53
|
const DEFAULT_I18N = {
|
|
16
54
|
moreOptions: 'More options',
|
|
17
55
|
};
|
|
@@ -112,6 +150,7 @@ export const MenuBarMixin = (superClass) =>
|
|
|
112
150
|
*/
|
|
113
151
|
items: {
|
|
114
152
|
type: Array,
|
|
153
|
+
sync: true,
|
|
115
154
|
value: () => [],
|
|
116
155
|
},
|
|
117
156
|
|
|
@@ -140,6 +179,7 @@ export const MenuBarMixin = (superClass) =>
|
|
|
140
179
|
*/
|
|
141
180
|
reverseCollapse: {
|
|
142
181
|
type: Boolean,
|
|
182
|
+
sync: true,
|
|
143
183
|
},
|
|
144
184
|
|
|
145
185
|
/**
|
|
@@ -149,6 +189,7 @@ export const MenuBarMixin = (superClass) =>
|
|
|
149
189
|
*/
|
|
150
190
|
tabNavigation: {
|
|
151
191
|
type: Boolean,
|
|
192
|
+
sync: true,
|
|
152
193
|
},
|
|
153
194
|
|
|
154
195
|
/**
|
|
@@ -169,6 +210,7 @@ export const MenuBarMixin = (superClass) =>
|
|
|
169
210
|
/** @protected */
|
|
170
211
|
_container: {
|
|
171
212
|
type: Object,
|
|
213
|
+
sync: true,
|
|
172
214
|
},
|
|
173
215
|
};
|
|
174
216
|
}
|
|
@@ -178,7 +220,7 @@ export const MenuBarMixin = (superClass) =>
|
|
|
178
220
|
'_themeChanged(_theme, _overflow, _container)',
|
|
179
221
|
'__hasOverflowChanged(_hasOverflow, _overflow)',
|
|
180
222
|
'__i18nChanged(__effectiveI18n, _overflow)',
|
|
181
|
-
'
|
|
223
|
+
'__updateButtons(items, disabled, _overflow, _container)',
|
|
182
224
|
'_reverseCollapseChanged(reverseCollapse, _overflow, _container)',
|
|
183
225
|
'_tabNavigationChanged(tabNavigation, _overflow, _container)',
|
|
184
226
|
];
|
|
@@ -235,6 +277,17 @@ export const MenuBarMixin = (superClass) =>
|
|
|
235
277
|
return false;
|
|
236
278
|
}
|
|
237
279
|
|
|
280
|
+
/**
|
|
281
|
+
* Override getter from `KeyboardDirectionMixin`.
|
|
282
|
+
*
|
|
283
|
+
* @return {boolean}
|
|
284
|
+
* @protected
|
|
285
|
+
* @override
|
|
286
|
+
*/
|
|
287
|
+
get _tabNavigation() {
|
|
288
|
+
return this.tabNavigation;
|
|
289
|
+
}
|
|
290
|
+
|
|
238
291
|
/**
|
|
239
292
|
* Override getter from `ResizeMixin` to observe parent.
|
|
240
293
|
*
|
|
@@ -273,8 +326,11 @@ export const MenuBarMixin = (superClass) =>
|
|
|
273
326
|
dots.innerHTML = '·'.repeat(3);
|
|
274
327
|
btn.appendChild(dots);
|
|
275
328
|
|
|
329
|
+
btn.setAttribute('aria-haspopup', 'true');
|
|
330
|
+
btn.setAttribute('aria-expanded', 'false');
|
|
331
|
+
btn.setAttribute('role', this.tabNavigation ? 'button' : 'menuitem');
|
|
332
|
+
|
|
276
333
|
this._overflow = btn;
|
|
277
|
-
this._initButtonAttrs(btn);
|
|
278
334
|
},
|
|
279
335
|
});
|
|
280
336
|
this.addController(this._overflowController);
|
|
@@ -329,23 +385,6 @@ export const MenuBarMixin = (superClass) =>
|
|
|
329
385
|
this.__detectOverflow();
|
|
330
386
|
}
|
|
331
387
|
|
|
332
|
-
/**
|
|
333
|
-
* Override method inherited from `DisabledMixin`
|
|
334
|
-
* to update the `disabled` property for the buttons
|
|
335
|
-
* whenever the property changes on the menu bar.
|
|
336
|
-
*
|
|
337
|
-
* @param {boolean} newValue the new disabled value
|
|
338
|
-
* @param {boolean} oldValue the previous disabled value
|
|
339
|
-
* @override
|
|
340
|
-
* @protected
|
|
341
|
-
*/
|
|
342
|
-
_disabledChanged(newValue, oldValue) {
|
|
343
|
-
super._disabledChanged(newValue, oldValue);
|
|
344
|
-
if (oldValue !== newValue) {
|
|
345
|
-
this.__updateButtonsDisabled(newValue);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
388
|
/**
|
|
350
389
|
* A callback for the `_theme` property observer.
|
|
351
390
|
* It propagates the host theme to the buttons and the sub menu.
|
|
@@ -355,14 +394,16 @@ export const MenuBarMixin = (superClass) =>
|
|
|
355
394
|
*/
|
|
356
395
|
_themeChanged(theme, overflow, container) {
|
|
357
396
|
if (overflow && container) {
|
|
358
|
-
this.
|
|
397
|
+
this.__renderButtons(this.items);
|
|
359
398
|
this.__detectOverflow();
|
|
360
|
-
}
|
|
361
399
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
400
|
+
if (theme) {
|
|
401
|
+
overflow.setAttribute('theme', theme);
|
|
402
|
+
this._subMenu.setAttribute('theme', theme);
|
|
403
|
+
} else {
|
|
404
|
+
overflow.removeAttribute('theme');
|
|
405
|
+
this._subMenu.removeAttribute('theme');
|
|
406
|
+
}
|
|
366
407
|
}
|
|
367
408
|
}
|
|
368
409
|
|
|
@@ -402,7 +443,7 @@ export const MenuBarMixin = (superClass) =>
|
|
|
402
443
|
}
|
|
403
444
|
|
|
404
445
|
/** @private */
|
|
405
|
-
|
|
446
|
+
__updateButtons(items, disabled, overflow, container) {
|
|
406
447
|
if (!overflow || !container) {
|
|
407
448
|
return;
|
|
408
449
|
}
|
|
@@ -410,11 +451,24 @@ export const MenuBarMixin = (superClass) =>
|
|
|
410
451
|
if (items !== this._oldItems) {
|
|
411
452
|
this._oldItems = items;
|
|
412
453
|
this.__renderButtons(items);
|
|
454
|
+
this.__detectOverflow();
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
if (disabled !== this._oldDisabled) {
|
|
458
|
+
this._oldDisabled = disabled;
|
|
459
|
+
this.__renderButtons(items);
|
|
460
|
+
overflow.toggleAttribute('disabled', disabled);
|
|
413
461
|
}
|
|
414
462
|
|
|
415
463
|
const subMenu = this._subMenu;
|
|
416
464
|
if (subMenu && subMenu.opened) {
|
|
417
|
-
subMenu.
|
|
465
|
+
const button = subMenu._overlayElement.positionTarget;
|
|
466
|
+
|
|
467
|
+
// Close sub-menu if the corresponding button is no longer in the DOM,
|
|
468
|
+
// or if the item on it has been changed to no longer have children.
|
|
469
|
+
if (!button.isConnected || !Array.isArray(button.item.children) || button.item.children.length === 0) {
|
|
470
|
+
subMenu.close();
|
|
471
|
+
}
|
|
418
472
|
}
|
|
419
473
|
}
|
|
420
474
|
|
|
@@ -438,9 +492,9 @@ export const MenuBarMixin = (superClass) =>
|
|
|
438
492
|
/** @private */
|
|
439
493
|
__restoreButtons(buttons) {
|
|
440
494
|
buttons.forEach((button) => {
|
|
441
|
-
button.disabled = (button.item && button.item.disabled) || this.disabled;
|
|
442
495
|
button.style.visibility = '';
|
|
443
496
|
button.style.position = '';
|
|
497
|
+
button.style.width = '';
|
|
444
498
|
|
|
445
499
|
// Teleport item component back from "overflow" sub-menu
|
|
446
500
|
const item = button.item && button.item.component;
|
|
@@ -460,14 +514,6 @@ export const MenuBarMixin = (superClass) =>
|
|
|
460
514
|
item.removeAttribute('tabindex');
|
|
461
515
|
}
|
|
462
516
|
|
|
463
|
-
/** @private */
|
|
464
|
-
__updateButtonsDisabled(disabled) {
|
|
465
|
-
this._buttons.forEach((btn) => {
|
|
466
|
-
// Disable the button if the entire menu-bar is disabled or the item alone is disabled
|
|
467
|
-
btn.disabled = disabled || (btn.item && btn.item.disabled);
|
|
468
|
-
});
|
|
469
|
-
}
|
|
470
|
-
|
|
471
517
|
/** @private */
|
|
472
518
|
__updateOverflow(items) {
|
|
473
519
|
this._overflow.item = { children: items };
|
|
@@ -501,7 +547,6 @@ export const MenuBarMixin = (superClass) =>
|
|
|
501
547
|
|
|
502
548
|
// Save width for buttons with component
|
|
503
549
|
btn.style.width = getComputedStyle(btn).width;
|
|
504
|
-
btn.disabled = true;
|
|
505
550
|
btn.style.visibility = 'hidden';
|
|
506
551
|
btn.style.position = 'absolute';
|
|
507
552
|
}
|
|
@@ -550,66 +595,17 @@ export const MenuBarMixin = (superClass) =>
|
|
|
550
595
|
});
|
|
551
596
|
}
|
|
552
597
|
|
|
553
|
-
/** @
|
|
554
|
-
|
|
555
|
-
this._buttons.forEach((button) => {
|
|
556
|
-
if (button !== this._overflow) {
|
|
557
|
-
this.removeChild(button);
|
|
558
|
-
}
|
|
559
|
-
});
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
/** @protected */
|
|
563
|
-
_initButton(item) {
|
|
564
|
-
const button = document.createElement('vaadin-menu-bar-button');
|
|
565
|
-
|
|
566
|
-
const itemCopy = { ...item };
|
|
567
|
-
button.item = itemCopy;
|
|
568
|
-
|
|
569
|
-
if (item.component) {
|
|
570
|
-
const component = this.__getComponent(itemCopy);
|
|
571
|
-
itemCopy.component = component;
|
|
572
|
-
// Save item for overflow menu
|
|
573
|
-
component.item = itemCopy;
|
|
574
|
-
button.appendChild(component);
|
|
575
|
-
} else if (item.text) {
|
|
576
|
-
button.textContent = item.text;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
if (item.className) {
|
|
580
|
-
button.className = item.className;
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
button.disabled = item.disabled;
|
|
584
|
-
|
|
585
|
-
return button;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
/** @protected */
|
|
589
|
-
_initButtonAttrs(button) {
|
|
590
|
-
button.setAttribute('role', this.tabNavigation ? 'button' : 'menuitem');
|
|
591
|
-
|
|
592
|
-
if (button === this._overflow || (button.item && button.item.children)) {
|
|
593
|
-
button.setAttribute('aria-haspopup', 'true');
|
|
594
|
-
button.setAttribute('aria-expanded', 'false');
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
/** @protected */
|
|
599
|
-
_setButtonTheme(btn, hostTheme) {
|
|
598
|
+
/** @private */
|
|
599
|
+
__getButtonTheme(item, hostTheme) {
|
|
600
600
|
let theme = hostTheme;
|
|
601
601
|
|
|
602
602
|
// Item theme takes precedence over host theme even if it's empty, as long as it's not undefined or null
|
|
603
|
-
const itemTheme =
|
|
603
|
+
const itemTheme = item && item.theme;
|
|
604
604
|
if (itemTheme != null) {
|
|
605
605
|
theme = Array.isArray(itemTheme) ? itemTheme.join(' ') : itemTheme;
|
|
606
606
|
}
|
|
607
607
|
|
|
608
|
-
|
|
609
|
-
btn.setAttribute('theme', theme);
|
|
610
|
-
} else {
|
|
611
|
-
btn.removeAttribute('theme');
|
|
612
|
-
}
|
|
608
|
+
return theme;
|
|
613
609
|
}
|
|
614
610
|
|
|
615
611
|
/** @private */
|
|
@@ -634,21 +630,47 @@ export const MenuBarMixin = (superClass) =>
|
|
|
634
630
|
|
|
635
631
|
/** @private */
|
|
636
632
|
__renderButtons(items = []) {
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
633
|
+
render(
|
|
634
|
+
html`
|
|
635
|
+
${items.map((item) => {
|
|
636
|
+
const itemCopy = { ...item };
|
|
637
|
+
const hasChildren = Boolean(item && item.children);
|
|
638
|
+
|
|
639
|
+
if (itemCopy.component) {
|
|
640
|
+
const component = this.__getComponent(itemCopy);
|
|
641
|
+
itemCopy.component = component;
|
|
642
|
+
component.item = itemCopy;
|
|
643
|
+
}
|
|
643
644
|
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
645
|
+
return html`
|
|
646
|
+
<vaadin-menu-bar-button
|
|
647
|
+
.item="${itemCopy}"
|
|
648
|
+
.disabled="${this.disabled || item.disabled}"
|
|
649
|
+
role="${this.tabNavigation ? 'button' : 'menuitem'}"
|
|
650
|
+
aria-haspopup="${ifDefined(hasChildren ? 'true' : nothing)}"
|
|
651
|
+
aria-expanded="${ifDefined(hasChildren ? 'false' : nothing)}"
|
|
652
|
+
class="${ifDefined(item.className || nothing)}"
|
|
653
|
+
theme="${ifDefined(this.__getButtonTheme(item, this._theme) || nothing)}"
|
|
654
|
+
@click="${this.__onRootButtonClick}"
|
|
655
|
+
>${componentDirective(itemCopy)}</vaadin-menu-bar-button
|
|
656
|
+
>
|
|
657
|
+
`;
|
|
658
|
+
})}
|
|
659
|
+
`,
|
|
660
|
+
this,
|
|
661
|
+
{ renderBefore: this._overflow },
|
|
662
|
+
);
|
|
663
|
+
}
|
|
650
664
|
|
|
651
|
-
|
|
665
|
+
/** @private */
|
|
666
|
+
__onRootButtonClick(event) {
|
|
667
|
+
const button = event.target;
|
|
668
|
+
// Propagate click event from button to the item component if it was outside
|
|
669
|
+
// it e.g. by calling `click()` on the button (used by the Flow counterpart).
|
|
670
|
+
if (button.item && button.item.component && !event.composedPath().includes(button.item.component)) {
|
|
671
|
+
event.stopPropagation();
|
|
672
|
+
button.item.component.click();
|
|
673
|
+
}
|
|
652
674
|
}
|
|
653
675
|
|
|
654
676
|
/**
|
|
@@ -759,12 +781,7 @@ export const MenuBarMixin = (superClass) =>
|
|
|
759
781
|
*/
|
|
760
782
|
_setFocused(focused) {
|
|
761
783
|
if (focused) {
|
|
762
|
-
|
|
763
|
-
if (this.tabNavigation) {
|
|
764
|
-
// Switch submenu on menu button Tab / Shift Tab
|
|
765
|
-
target = this.querySelector('[focused]');
|
|
766
|
-
this.__switchSubMenu(target);
|
|
767
|
-
}
|
|
784
|
+
const target = this.tabNavigation ? this.querySelector('[focused]') : this.querySelector('[tabindex="0"]');
|
|
768
785
|
if (target) {
|
|
769
786
|
this._buttons.forEach((btn) => {
|
|
770
787
|
this._setTabindex(btn, btn === target);
|
|
@@ -883,30 +900,15 @@ export const MenuBarMixin = (superClass) =>
|
|
|
883
900
|
if (e.keyCode === 38 && item === list.items[0]) {
|
|
884
901
|
this._close(true);
|
|
885
902
|
}
|
|
886
|
-
// ArrowLeft, or ArrowRight on non-parent submenu item
|
|
903
|
+
// ArrowLeft, or ArrowRight on non-parent submenu item,
|
|
887
904
|
if (e.keyCode === 37 || (e.keyCode === 39 && !item._item.children)) {
|
|
888
905
|
// Prevent ArrowLeft from being handled in context-menu
|
|
889
906
|
e.stopImmediatePropagation();
|
|
890
907
|
this._onKeyDown(e);
|
|
891
|
-
} else if (e.keyCode === 9 && this.tabNavigation) {
|
|
892
|
-
// Switch opened submenu on submenu item Tab / Shift Tab
|
|
893
|
-
const items = this._getItems() || [];
|
|
894
|
-
const currentIdx = items.indexOf(this.focused);
|
|
895
|
-
const increment = e.shiftKey ? -1 : 1;
|
|
896
|
-
let idx = currentIdx + increment;
|
|
897
|
-
idx = this._getAvailableIndex(items, idx, increment, (item) => !isElementHidden(item));
|
|
898
|
-
this.__switchSubMenu(items[idx]);
|
|
899
908
|
}
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
909
|
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
const wasExpanded = this._expandedButton != null && this._expandedButton !== target;
|
|
906
|
-
if (wasExpanded) {
|
|
907
|
-
this._close();
|
|
908
|
-
if (target.item && target.item.children) {
|
|
909
|
-
this.__openSubMenu(target, true, { keepFocus: true });
|
|
910
|
+
if (e.key === 'Tab' && this.tabNavigation) {
|
|
911
|
+
this._onKeyDown(e);
|
|
910
912
|
}
|
|
911
913
|
}
|
|
912
914
|
}
|
|
@@ -951,31 +953,21 @@ export const MenuBarMixin = (superClass) =>
|
|
|
951
953
|
const overlay = subMenu._overlayElement;
|
|
952
954
|
overlay.noVerticalOverlap = true;
|
|
953
955
|
|
|
954
|
-
this.
|
|
955
|
-
|
|
956
|
-
requestAnimationFrame(() => {
|
|
957
|
-
// After changing items, buttons are recreated so the old button is
|
|
958
|
-
// no longer in the DOM. Reset position target to null to prevent
|
|
959
|
-
// overlay from closing due to target width / height equal to 0.
|
|
960
|
-
if (overlay.positionTarget && !overlay.positionTarget.isConnected) {
|
|
961
|
-
overlay.positionTarget = null;
|
|
962
|
-
}
|
|
963
|
-
|
|
964
|
-
button.dispatchEvent(
|
|
965
|
-
new CustomEvent('opensubmenu', {
|
|
966
|
-
detail: {
|
|
967
|
-
children: items,
|
|
968
|
-
},
|
|
969
|
-
}),
|
|
970
|
-
);
|
|
971
|
-
this._hideTooltip(true);
|
|
972
|
-
|
|
973
|
-
this._setExpanded(button, true);
|
|
956
|
+
this._hideTooltip(true);
|
|
974
957
|
|
|
975
|
-
|
|
976
|
-
|
|
958
|
+
this._expandedButton = button;
|
|
959
|
+
this._setExpanded(button, true);
|
|
977
960
|
|
|
978
961
|
this.style.pointerEvents = 'auto';
|
|
962
|
+
overlay.positionTarget = button;
|
|
963
|
+
|
|
964
|
+
button.dispatchEvent(
|
|
965
|
+
new CustomEvent('opensubmenu', {
|
|
966
|
+
detail: {
|
|
967
|
+
children: items,
|
|
968
|
+
},
|
|
969
|
+
}),
|
|
970
|
+
);
|
|
979
971
|
|
|
980
972
|
overlay.addEventListener(
|
|
981
973
|
'vaadin-overlay-open',
|
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": "24.8.0-
|
|
4
|
+
"version": "24.8.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```\n<vaadin-menu-bar></vaadin-menu-bar>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/24.8.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```\n<vaadin-menu-bar></vaadin-menu-bar>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/24.8.0-beta1/#/elements/vaadin-menu-bar#property-items) property to initialize the structure:\n\n```\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/24.8.0-beta1/#/elements/vaadin-button).\n- `<vaadin-menu-bar-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/24.8.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/24.8.0-beta1/#/elements/vaadin-list-box).\n- `<vaadin-menu-bar-overlay>` - has the same API as [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/24.8.0-beta1/#/elements/vaadin-overlay).\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.\n\nNote: the `theme` attribute value set on `<vaadin-menu-bar>` is\npropagated to the internal components listed above.",
|
|
12
12
|
"attributes": [
|
|
13
13
|
{
|
|
14
14
|
"name": "disabled",
|
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": "24.8.0-
|
|
4
|
+
"version": "24.8.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```\n<vaadin-menu-bar></vaadin-menu-bar>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/24.8.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```\n<vaadin-menu-bar></vaadin-menu-bar>\n```\n\nAnd then use [`items`](https://cdn.vaadin.com/vaadin-web-components/24.8.0-beta1/#/elements/vaadin-menu-bar#property-items) property to initialize the structure:\n\n```\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/24.8.0-beta1/#/elements/vaadin-button).\n- `<vaadin-menu-bar-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/24.8.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/24.8.0-beta1/#/elements/vaadin-list-box).\n- `<vaadin-menu-bar-overlay>` - has the same API as [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/24.8.0-beta1/#/elements/vaadin-overlay).\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.\n\nNote: the `theme` attribute value set on `<vaadin-menu-bar>` is\npropagated to the internal components listed above.",
|
|
20
20
|
"extension": true,
|
|
21
21
|
"attributes": [
|
|
22
22
|
{
|