@vaadin/menu-bar 25.0.0-alpha1 → 25.0.0-alpha11

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.
Files changed (35) hide show
  1. package/package.json +15 -16
  2. package/src/styles/vaadin-menu-bar-base-styles.d.ts +8 -0
  3. package/src/styles/vaadin-menu-bar-base-styles.js +55 -0
  4. package/src/styles/vaadin-menu-bar-button-base-styles.d.ts +8 -0
  5. package/src/styles/vaadin-menu-bar-button-base-styles.js +47 -0
  6. package/src/styles/vaadin-menu-bar-item-base-styles.d.ts +8 -0
  7. package/src/styles/vaadin-menu-bar-item-base-styles.js +8 -0
  8. package/src/styles/vaadin-menu-bar-overlay-base-styles.d.ts +8 -0
  9. package/src/styles/vaadin-menu-bar-overlay-base-styles.js +9 -0
  10. package/src/vaadin-menu-bar-button.js +2 -13
  11. package/src/vaadin-menu-bar-item.js +5 -11
  12. package/src/vaadin-menu-bar-list-box.js +5 -18
  13. package/src/vaadin-menu-bar-mixin.js +145 -130
  14. package/src/vaadin-menu-bar-overlay.js +7 -4
  15. package/src/vaadin-menu-bar-submenu-mixin.js +3 -3
  16. package/src/vaadin-menu-bar-submenu.js +20 -11
  17. package/src/vaadin-menu-bar.d.ts +3 -6
  18. package/src/vaadin-menu-bar.js +11 -27
  19. package/vaadin-menu-bar.js +1 -1
  20. package/web-types.json +2 -2
  21. package/web-types.lit.json +2 -2
  22. package/theme/lumo/vaadin-menu-bar-button-styles.d.ts +0 -1
  23. package/theme/lumo/vaadin-menu-bar-button-styles.js +0 -128
  24. package/theme/lumo/vaadin-menu-bar-button.d.ts +0 -2
  25. package/theme/lumo/vaadin-menu-bar-button.js +0 -2
  26. package/theme/lumo/vaadin-menu-bar-item-styles.d.ts +0 -2
  27. package/theme/lumo/vaadin-menu-bar-item-styles.js +0 -27
  28. package/theme/lumo/vaadin-menu-bar-list-box-styles.d.ts +0 -1
  29. package/theme/lumo/vaadin-menu-bar-list-box-styles.js +0 -5
  30. package/theme/lumo/vaadin-menu-bar-overlay-styles.d.ts +0 -1
  31. package/theme/lumo/vaadin-menu-bar-overlay-styles.js +0 -13
  32. package/theme/lumo/vaadin-menu-bar-styles.d.ts +0 -1
  33. package/theme/lumo/vaadin-menu-bar-styles.js +0 -17
  34. package/theme/lumo/vaadin-menu-bar.d.ts +0 -6
  35. 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-alpha1",
3
+ "version": "25.0.0-alpha11",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -21,7 +21,6 @@
21
21
  "type": "module",
22
22
  "files": [
23
23
  "src",
24
- "theme",
25
24
  "vaadin-*.d.ts",
26
25
  "vaadin-*.js",
27
26
  "web-types.json",
@@ -35,27 +34,27 @@
35
34
  ],
36
35
  "dependencies": {
37
36
  "@open-wc/dedupe-mixin": "^1.3.0",
38
- "@vaadin/a11y-base": "25.0.0-alpha1",
39
- "@vaadin/button": "25.0.0-alpha1",
40
- "@vaadin/component-base": "25.0.0-alpha1",
41
- "@vaadin/context-menu": "25.0.0-alpha1",
42
- "@vaadin/item": "25.0.0-alpha1",
43
- "@vaadin/list-box": "25.0.0-alpha1",
44
- "@vaadin/overlay": "25.0.0-alpha1",
45
- "@vaadin/vaadin-lumo-styles": "25.0.0-alpha1",
46
- "@vaadin/vaadin-themable-mixin": "25.0.0-alpha1",
37
+ "@vaadin/a11y-base": "25.0.0-alpha11",
38
+ "@vaadin/button": "25.0.0-alpha11",
39
+ "@vaadin/component-base": "25.0.0-alpha11",
40
+ "@vaadin/context-menu": "25.0.0-alpha11",
41
+ "@vaadin/item": "25.0.0-alpha11",
42
+ "@vaadin/list-box": "25.0.0-alpha11",
43
+ "@vaadin/overlay": "25.0.0-alpha11",
44
+ "@vaadin/vaadin-themable-mixin": "25.0.0-alpha11",
47
45
  "lit": "^3.0.0"
48
46
  },
49
47
  "devDependencies": {
50
- "@vaadin/chai-plugins": "25.0.0-alpha1",
51
- "@vaadin/icon": "25.0.0-alpha1",
52
- "@vaadin/test-runner-commands": "25.0.0-alpha1",
53
- "@vaadin/testing-helpers": "^1.1.0",
48
+ "@vaadin/chai-plugins": "25.0.0-alpha11",
49
+ "@vaadin/icon": "25.0.0-alpha11",
50
+ "@vaadin/test-runner-commands": "25.0.0-alpha11",
51
+ "@vaadin/testing-helpers": "^2.0.0",
52
+ "@vaadin/vaadin-lumo-styles": "25.0.0-alpha11",
54
53
  "sinon": "^18.0.0"
55
54
  },
56
55
  "web-types": [
57
56
  "web-types.json",
58
57
  "web-types.lit.json"
59
58
  ],
60
- "gitHead": "b8c22a4a0c64156210d0daac96b43ae4e5526d49"
59
+ "gitHead": "abfd315ba5a7484a613e0768635a4e8fe945a44b"
61
60
  }
@@ -0,0 +1,8 @@
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 type { CSSResult } from 'lit';
7
+
8
+ export const menuBarStyles: CSSResult;
@@ -0,0 +1,55 @@
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
+ display: flex;
19
+ flex-wrap: nowrap;
20
+ margin: calc((var(--vaadin-focus-ring-width) + 1px) * -1);
21
+ overflow: hidden;
22
+ padding: calc(var(--vaadin-focus-ring-width) + 1px);
23
+ position: relative;
24
+ width: 100%;
25
+ --_gap: var(--vaadin-menu-bar-gap, 0px);
26
+ --_bw: var(--vaadin-button-border-width, 1px);
27
+ gap: var(--_gap);
28
+ --_rad-button: var(--vaadin-button-border-radius, var(--vaadin-radius-m));
29
+ --_rad: min(var(--_gap) * 1000, var(--_rad-button));
30
+ }
31
+
32
+ ::slotted(vaadin-menu-bar-button:not(:first-of-type)) {
33
+ margin-inline-start: min(var(--_bw) * -1 + var(--_gap) * 1000, 0px);
34
+ }
35
+
36
+ ::slotted(vaadin-menu-bar-button) {
37
+ border-radius: var(--_rad);
38
+ }
39
+
40
+ ::slotted([first-visible]),
41
+ :host([has-single-button]) ::slotted([slot='overflow']) {
42
+ border-start-start-radius: var(--_rad-button);
43
+ border-end-start-radius: var(--_rad-button);
44
+ }
45
+
46
+ ::slotted(:is([last-visible], [slot='overflow'])) {
47
+ border-start-end-radius: var(--_rad-button);
48
+ border-end-end-radius: var(--_rad-button);
49
+ }
50
+
51
+ :host([theme~='end-aligned']) ::slotted(vaadin-menu-bar-button[first-visible]),
52
+ :host([theme~='end-aligned'][has-single-button]) ::slotted(vaadin-menu-bar-button) {
53
+ margin-inline-start: auto;
54
+ }
55
+ `;
@@ -0,0 +1,8 @@
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 type { CSSResult } from 'lit';
7
+
8
+ export const menuBarButtonStyles: CSSResult;
@@ -0,0 +1,47 @@
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([focus-ring]) {
14
+ z-index: 1;
15
+ }
16
+
17
+ :host([slot='overflow']) {
18
+ margin-inline-end: 0;
19
+ }
20
+
21
+ .vaadin-button-container {
22
+ gap: inherit;
23
+ }
24
+
25
+ :host(:not([slot='overflow']):not([theme~='icon'])[aria-haspopup]) [part='suffix'] {
26
+ display: flex;
27
+ align-items: center;
28
+ gap: inherit;
29
+ }
30
+
31
+ :host(:not([slot='overflow']):not([theme~='icon'])[aria-haspopup]) [part='suffix']::after {
32
+ background: currentColor;
33
+ content: '';
34
+ height: var(--vaadin-icon-size, 1lh);
35
+ mask-image: var(--_vaadin-icon-chevron-down);
36
+ width: var(--vaadin-icon-size, 1lh);
37
+ }
38
+
39
+ ::slotted(vaadin-menu-bar-item) {
40
+ padding: 0;
41
+ gap: 0;
42
+ }
43
+
44
+ ::slotted(vaadin-menu-bar-item)::after {
45
+ display: none;
46
+ }
47
+ `;
@@ -0,0 +1,8 @@
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 type { CSSResult } from 'lit';
7
+
8
+ export const menuBarItemStyles: CSSResult;
@@ -0,0 +1,8 @@
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 { contextMenuItemStyles } from '@vaadin/context-menu/src/styles/vaadin-context-menu-item-base-styles.js';
7
+
8
+ export const menuBarItemStyles = contextMenuItemStyles;
@@ -0,0 +1,8 @@
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 type { CSSResult } from 'lit';
7
+
8
+ export const menuBarOverlayStyles: CSSResult;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2016 - 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-base-styles.js';
7
+ import { overlayStyles } from '@vaadin/overlay/src/styles/vaadin-overlay-base-styles.js';
8
+
9
+ export const menuBarOverlayStyles = [overlayStyles, menuOverlayStyles];
@@ -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 { css } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
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.
@@ -20,18 +20,7 @@ class MenuBarButton extends Button {
20
20
  }
21
21
 
22
22
  static get styles() {
23
- return [
24
- super.styles,
25
- css`
26
- :host {
27
- flex-shrink: 0;
28
- }
29
-
30
- :host([slot='overflow']) {
31
- margin-inline-end: 0;
32
- }
33
- `,
34
- ];
23
+ return [super.styles, menuBarButtonStyles];
35
24
  }
36
25
 
37
26
  /**
@@ -3,12 +3,14 @@
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 { css, html, LitElement } from 'lit';
6
+ import { html, LitElement } from 'lit';
7
7
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
8
8
  import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
9
9
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
10
10
  import { ItemMixin } from '@vaadin/item/src/vaadin-item-mixin.js';
11
+ import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
11
12
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
13
+ import { menuBarItemStyles } from './styles/vaadin-menu-bar-item-base-styles.js';
12
14
 
13
15
  /**
14
16
  * An element used internally by `<vaadin-menu-bar>`. Not intended to be used separately.
@@ -20,21 +22,13 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
20
22
  * @mixes ThemableMixin
21
23
  * @protected
22
24
  */
23
- class MenuBarItem extends ItemMixin(ThemableMixin(DirMixin(PolylitMixin(LitElement)))) {
25
+ class MenuBarItem extends ItemMixin(ThemableMixin(DirMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
24
26
  static get is() {
25
27
  return 'vaadin-menu-bar-item';
26
28
  }
27
29
 
28
30
  static get styles() {
29
- return css`
30
- :host {
31
- display: inline-block;
32
- }
33
-
34
- :host([hidden]) {
35
- display: none !important;
36
- }
37
- `;
31
+ return menuBarItemStyles;
38
32
  }
39
33
 
40
34
  /** @protected */
@@ -3,11 +3,13 @@
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 { css, html, LitElement } from 'lit';
6
+ import { html, LitElement } from 'lit';
7
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-base-styles.js';
12
+ import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
11
13
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
12
14
 
13
15
  /**
@@ -20,28 +22,13 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
20
22
  * @mixes ThemableMixin
21
23
  * @protected
22
24
  */
23
- class MenuBarListBox extends ListMixin(ThemableMixin(DirMixin(PolylitMixin(LitElement)))) {
25
+ class MenuBarListBox extends ListMixin(ThemableMixin(DirMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
24
26
  static get is() {
25
27
  return 'vaadin-menu-bar-list-box';
26
28
  }
27
29
 
28
30
  static get styles() {
29
- return css`
30
- :host {
31
- display: flex;
32
- }
33
-
34
- :host([hidden]) {
35
- display: none !important;
36
- }
37
-
38
- [part='items'] {
39
- height: 100%;
40
- width: 100%;
41
- overflow-y: auto;
42
- -webkit-overflow-scrolling: touch;
43
- }
44
- `;
31
+ return listBoxStyles;
45
32
  }
46
33
 
47
34
  static get properties() {
@@ -10,6 +10,8 @@ import { DisabledMixin } from '@vaadin/a11y-base/src/disabled-mixin.js';
10
10
  import { FocusMixin } from '@vaadin/a11y-base/src/focus-mixin.js';
11
11
  import { isElementFocused, isKeyboardActive } from '@vaadin/a11y-base/src/focus-utils.js';
12
12
  import { KeyboardDirectionMixin } from '@vaadin/a11y-base/src/keyboard-direction-mixin.js';
13
+ import { microTask } from '@vaadin/component-base/src/async.js';
14
+ import { Debouncer } from '@vaadin/component-base/src/debounce.js';
13
15
  import { I18nMixin } from '@vaadin/component-base/src/i18n-mixin.js';
14
16
  import { ResizeMixin } from '@vaadin/component-base/src/resize-mixin.js';
15
17
  import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
@@ -189,41 +191,9 @@ export const MenuBarMixin = (superClass) =>
189
191
  type: Boolean,
190
192
  sync: true,
191
193
  },
192
-
193
- /**
194
- * @type {boolean}
195
- * @protected
196
- */
197
- _hasOverflow: {
198
- type: Boolean,
199
- value: false,
200
- sync: true,
201
- },
202
-
203
- /** @protected */
204
- _overflow: {
205
- type: Object,
206
- },
207
-
208
- /** @protected */
209
- _container: {
210
- type: Object,
211
- sync: true,
212
- },
213
194
  };
214
195
  }
215
196
 
216
- static get observers() {
217
- return [
218
- '_themeChanged(_theme, _overflow, _container)',
219
- '__hasOverflowChanged(_hasOverflow, _overflow)',
220
- '__i18nChanged(__effectiveI18n, _overflow)',
221
- '__updateButtons(items, disabled, _overflow, _container)',
222
- '_reverseCollapseChanged(reverseCollapse, _overflow, _container)',
223
- '_tabNavigationChanged(tabNavigation, _overflow, _container)',
224
- ];
225
- }
226
-
227
197
  /**
228
198
  * The object used to localize this component. To change the default
229
199
  * localization, replace this with an object that provides all properties, or
@@ -305,8 +275,15 @@ export const MenuBarMixin = (superClass) =>
305
275
  }
306
276
 
307
277
  /** @private */
308
- get _subMenu() {
309
- return this.shadowRoot.querySelector('vaadin-menu-bar-submenu');
278
+ get _hasOverflow() {
279
+ return this._overflow && !this._overflow.hasAttribute('hidden');
280
+ }
281
+
282
+ /** @private */
283
+ set _hasOverflow(hasOverflow) {
284
+ if (this._overflow) {
285
+ this._overflow.toggleAttribute('hidden', !hasOverflow);
286
+ }
310
287
  }
311
288
 
312
289
  /** @protected */
@@ -315,6 +292,20 @@ export const MenuBarMixin = (superClass) =>
315
292
 
316
293
  this.setAttribute('role', 'menubar');
317
294
 
295
+ this._subMenuController = new SlotController(this, 'submenu', 'vaadin-menu-bar-submenu', {
296
+ initializer: (menu) => {
297
+ menu.setAttribute('is-root', '');
298
+
299
+ menu.addEventListener('item-selected', this.__onItemSelected.bind(this));
300
+ menu.addEventListener('close-all-menus', this.__onEscapeClose.bind(this));
301
+
302
+ const overlay = menu._overlayElement;
303
+ overlay._contentRoot.addEventListener('keydown', this.__boundOnContextMenuKeydown);
304
+
305
+ this._subMenu = menu;
306
+ },
307
+ });
308
+
318
309
  this._overflowController = new SlotController(this, 'overflow', 'vaadin-menu-bar-button', {
319
310
  initializer: (btn) => {
320
311
  btn.setAttribute('hidden', '');
@@ -331,27 +322,51 @@ export const MenuBarMixin = (superClass) =>
331
322
  this._overflow = btn;
332
323
  },
333
324
  });
325
+
326
+ this.addController(this._subMenuController);
334
327
  this.addController(this._overflowController);
335
328
 
336
329
  this.addEventListener('mousedown', () => this._hideTooltip(true));
337
330
  this.addEventListener('mouseleave', () => this._hideTooltip());
338
331
 
339
- this._subMenu.addEventListener('item-selected', this.__onItemSelected.bind(this));
340
- this._subMenu.addEventListener('close-all-menus', this.__onEscapeClose.bind(this));
332
+ this._container = this.shadowRoot.querySelector('[part="container"]');
333
+ }
341
334
 
342
- const overlay = this._subMenu._overlayElement;
343
- overlay.addEventListener('keydown', this.__boundOnContextMenuKeydown);
335
+ /** @protected */
336
+ updated(props) {
337
+ super.updated(props);
344
338
 
345
- const container = this.shadowRoot.querySelector('[part="container"]');
346
- container.addEventListener('click', this.__onButtonClick.bind(this));
347
- container.addEventListener('mouseover', (e) => this._onMouseOver(e));
339
+ if (props.has('items') || props.has('_theme') || props.has('disabled')) {
340
+ this.__renderButtons(this.items);
341
+ }
348
342
 
349
- // Delay setting container to avoid rendering buttons immediately,
350
- // which would also trigger detecting overflow and force re-layout
351
- // See https://github.com/vaadin/web-components/issues/7271
352
- queueMicrotask(() => {
353
- this._container = container;
354
- });
343
+ if (props.has('items') || props.has('_theme') || props.has('reverseCollapse')) {
344
+ this.__scheduleOverflow();
345
+ }
346
+
347
+ if (props.has('items')) {
348
+ this.__updateSubMenu();
349
+ }
350
+
351
+ if (props.has('overlayClass')) {
352
+ this._subMenu.overlayClass = this.overlayClass;
353
+ }
354
+
355
+ if (props.has('_theme')) {
356
+ this._themeChanged(this._theme);
357
+ }
358
+
359
+ if (props.has('disabled')) {
360
+ this._overflow.toggleAttribute('disabled', this.disabled);
361
+ }
362
+
363
+ if (props.has('tabNavigation')) {
364
+ this._tabNavigationChanged(this.tabNavigation);
365
+ }
366
+
367
+ if (props.has('__effectiveI18n')) {
368
+ this.__i18nChanged(this.__effectiveI18n);
369
+ }
355
370
  }
356
371
 
357
372
  /**
@@ -380,84 +395,37 @@ export const MenuBarMixin = (superClass) =>
380
395
  * @override
381
396
  */
382
397
  _onResize() {
383
- this.__detectOverflow();
384
- }
385
-
386
- /**
387
- * A callback for the `_theme` property observer.
388
- * It propagates the host theme to the buttons and the sub menu.
389
- *
390
- * @param {string | null} theme
391
- * @private
392
- */
393
- _themeChanged(theme, overflow, container) {
394
- if (overflow && container) {
395
- this.__renderButtons(this.items);
396
- this.__detectOverflow();
397
-
398
- if (theme) {
399
- overflow.setAttribute('theme', theme);
400
- this._subMenu.setAttribute('theme', theme);
401
- } else {
402
- overflow.removeAttribute('theme');
403
- this._subMenu.removeAttribute('theme');
404
- }
405
- }
406
- }
407
-
408
- /**
409
- * A callback for the 'reverseCollapse' property observer.
410
- *
411
- * @param {boolean | null} _reverseCollapse
412
- * @private
413
- */
414
- _reverseCollapseChanged(_reverseCollapse, overflow, container) {
415
- if (overflow && container) {
416
- this.__detectOverflow();
417
- }
398
+ this.__scheduleOverflow();
418
399
  }
419
400
 
420
401
  /** @private */
421
- _tabNavigationChanged(tabNavigation, overflow, container) {
422
- if (overflow && container) {
423
- const target = this.querySelector('[tabindex="0"]');
424
- this._buttons.forEach((btn) => {
425
- if (target) {
426
- this._setTabindex(btn, btn === target);
427
- } else {
428
- this._setTabindex(btn, false);
429
- }
430
- btn.setAttribute('role', tabNavigation ? 'button' : 'menuitem');
431
- });
402
+ _themeChanged(theme) {
403
+ if (theme) {
404
+ this._overflow.setAttribute('theme', theme);
405
+ this._subMenu.setAttribute('theme', theme);
406
+ } else {
407
+ this._overflow.removeAttribute('theme');
408
+ this._subMenu.removeAttribute('theme');
432
409
  }
433
- this.setAttribute('role', tabNavigation ? 'group' : 'menubar');
434
410
  }
435
411
 
436
412
  /** @private */
437
- __hasOverflowChanged(hasOverflow, overflow) {
438
- if (overflow) {
439
- overflow.toggleAttribute('hidden', !hasOverflow);
440
- }
413
+ _tabNavigationChanged(tabNavigation) {
414
+ const target = this.querySelector('[tabindex="0"]');
415
+ this._buttons.forEach((btn) => {
416
+ if (target) {
417
+ this._setTabindex(btn, btn === target);
418
+ } else {
419
+ this._setTabindex(btn, false);
420
+ }
421
+ btn.setAttribute('role', tabNavigation ? 'button' : 'menuitem');
422
+ });
423
+
424
+ this.setAttribute('role', tabNavigation ? 'group' : 'menubar');
441
425
  }
442
426
 
443
427
  /** @private */
444
- __updateButtons(items, disabled, overflow, container) {
445
- if (!overflow || !container) {
446
- return;
447
- }
448
-
449
- if (items !== this._oldItems) {
450
- this._oldItems = items;
451
- this.__renderButtons(items);
452
- this.__detectOverflow();
453
- }
454
-
455
- if (disabled !== this._oldDisabled) {
456
- this._oldDisabled = disabled;
457
- this.__renderButtons(items);
458
- overflow.toggleAttribute('disabled', disabled);
459
- }
460
-
428
+ __updateSubMenu() {
461
429
  const subMenu = this._subMenu;
462
430
  if (subMenu && subMenu.opened) {
463
431
  const button = subMenu._overlayElement.positionTarget;
@@ -471,12 +439,12 @@ export const MenuBarMixin = (superClass) =>
471
439
  }
472
440
 
473
441
  /** @private */
474
- __i18nChanged(effectiveI18n, overflow) {
475
- if (overflow && effectiveI18n && effectiveI18n.moreOptions !== undefined) {
442
+ __i18nChanged(effectiveI18n) {
443
+ if (effectiveI18n && effectiveI18n.moreOptions !== undefined) {
476
444
  if (effectiveI18n.moreOptions) {
477
- overflow.setAttribute('aria-label', effectiveI18n.moreOptions);
445
+ this._overflow.setAttribute('aria-label', effectiveI18n.moreOptions);
478
446
  } else {
479
- overflow.removeAttribute('aria-label');
447
+ this._overflow.removeAttribute('aria-label');
480
448
  }
481
449
  }
482
450
  }
@@ -561,11 +529,14 @@ export const MenuBarMixin = (superClass) =>
561
529
  }
562
530
 
563
531
  /** @private */
564
- __detectOverflow() {
565
- if (!this._container) {
566
- return;
567
- }
532
+ __scheduleOverflow() {
533
+ this._overflowDebouncer = Debouncer.debounce(this._overflowDebouncer, microTask, () => {
534
+ this.__detectOverflow();
535
+ });
536
+ }
568
537
 
538
+ /** @private */
539
+ __detectOverflow() {
569
540
  const overflow = this._overflow;
570
541
  const buttons = this._buttons.filter((btn) => btn !== overflow);
571
542
  const oldOverflowCount = this.__getOverflowCount(overflow);
@@ -707,6 +678,7 @@ export const MenuBarMixin = (superClass) =>
707
678
  _hideTooltip(immediate) {
708
679
  const tooltip = this._tooltipController && this._tooltipController.node;
709
680
  if (tooltip) {
681
+ this._tooltipController.setContext({ item: null });
710
682
  tooltip._stateController.close(immediate);
711
683
  }
712
684
  }
@@ -770,6 +742,34 @@ export const MenuBarMixin = (superClass) =>
770
742
  return Array.from(e.composedPath()).find((el) => el.localName === 'vaadin-menu-bar-button');
771
743
  }
772
744
 
745
+ /**
746
+ * Override method inherited from `FocusMixin`
747
+ *
748
+ * @override
749
+ * @protected
750
+ */
751
+ _shouldSetFocus(event) {
752
+ // Ignore events from the submenu
753
+ if (event.composedPath().includes(this._subMenu)) {
754
+ return false;
755
+ }
756
+ return super._shouldSetFocus(event);
757
+ }
758
+
759
+ /**
760
+ * Override method inherited from `FocusMixin`
761
+ *
762
+ * @override
763
+ * @protected
764
+ */
765
+ _shouldRemoveFocus(event) {
766
+ // Ignore events from the submenu
767
+ if (event.composedPath().includes(this._subMenu)) {
768
+ return false;
769
+ }
770
+ return super._shouldRemoveFocus(event);
771
+ }
772
+
773
773
  /**
774
774
  * Override method inherited from `FocusMixin`
775
775
  *
@@ -852,6 +852,16 @@ export const MenuBarMixin = (superClass) =>
852
852
  * @override
853
853
  */
854
854
  _onKeyDown(event) {
855
+ // Ignore events from the submenu
856
+ if (event.composedPath().includes(this._subMenu)) {
857
+ return;
858
+ }
859
+
860
+ this._handleKeyDown(event);
861
+ }
862
+
863
+ /** @private */
864
+ _handleKeyDown(event) {
855
865
  switch (event.key) {
856
866
  case 'ArrowDown':
857
867
  this._onArrowDown(event);
@@ -866,11 +876,16 @@ export const MenuBarMixin = (superClass) =>
866
876
  }
867
877
 
868
878
  /**
869
- * @param {!MouseEvent} e
879
+ * @param {!MouseEvent} event
870
880
  * @protected
871
881
  */
872
- _onMouseOver(e) {
873
- const button = this._getButtonFromEvent(e);
882
+ _onMouseOver(event) {
883
+ // Ignore events from the submenu
884
+ if (event.composedPath().includes(this._subMenu)) {
885
+ return;
886
+ }
887
+
888
+ const button = this._getButtonFromEvent(event);
874
889
  if (!button) {
875
890
  // Hide tooltip on mouseover to disabled button
876
891
  this._hideTooltip();
@@ -902,11 +917,11 @@ export const MenuBarMixin = (superClass) =>
902
917
  if (e.keyCode === 37 || (e.keyCode === 39 && !item._item.children)) {
903
918
  // Prevent ArrowLeft from being handled in context-menu
904
919
  e.stopImmediatePropagation();
905
- this._onKeyDown(e);
920
+ this._handleKeyDown(e);
906
921
  }
907
922
 
908
923
  if (e.key === 'Tab' && this.tabNavigation) {
909
- this._onKeyDown(e);
924
+ this._handleKeyDown(e);
910
925
  }
911
926
  }
912
927
  }
@@ -989,13 +1004,13 @@ export const MenuBarMixin = (superClass) =>
989
1004
 
990
1005
  /** @private */
991
1006
  _focusFirstItem() {
992
- const list = this._subMenu._overlayElement.firstElementChild;
1007
+ const list = this._subMenu._overlayElement._contentRoot.firstElementChild;
993
1008
  list.focus();
994
1009
  }
995
1010
 
996
1011
  /** @private */
997
1012
  _focusLastItem() {
998
- const list = this._subMenu._overlayElement.firstElementChild;
1013
+ const list = this._subMenu._overlayElement._contentRoot.firstElementChild;
999
1014
  const item = list.items[list.items.length - 1];
1000
1015
  if (item) {
1001
1016
  item.focus();
@@ -8,10 +8,10 @@ import { defineCustomElement } from '@vaadin/component-base/src/define.js';
8
8
  import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
9
9
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
10
10
  import { MenuOverlayMixin } from '@vaadin/context-menu/src/vaadin-menu-overlay-mixin.js';
11
- import { styles } from '@vaadin/context-menu/src/vaadin-menu-overlay-styles.js';
12
11
  import { OverlayMixin } from '@vaadin/overlay/src/vaadin-overlay-mixin.js';
13
- import { overlayStyles } from '@vaadin/overlay/src/vaadin-overlay-styles.js';
12
+ import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
14
13
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
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.
@@ -24,13 +24,15 @@ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mix
24
24
  * @mixes ThemableMixin
25
25
  * @protected
26
26
  */
27
- export class MenuBarOverlay extends MenuOverlayMixin(OverlayMixin(DirMixin(ThemableMixin(PolylitMixin(LitElement))))) {
27
+ export class MenuBarOverlay extends MenuOverlayMixin(
28
+ OverlayMixin(DirMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement))))),
29
+ ) {
28
30
  static get is() {
29
31
  return 'vaadin-menu-bar-overlay';
30
32
  }
31
33
 
32
34
  static get styles() {
33
- return [overlayStyles, styles];
35
+ return menuBarOverlayStyles;
34
36
  }
35
37
 
36
38
  /** @protected */
@@ -40,6 +42,7 @@ export class MenuBarOverlay extends MenuOverlayMixin(OverlayMixin(DirMixin(Thema
40
42
  <div part="overlay" id="overlay" tabindex="0">
41
43
  <div part="content" id="content">
42
44
  <slot></slot>
45
+ <slot name="submenu"></slot>
43
46
  </div>
44
47
  </div>
45
48
  `;
@@ -31,8 +31,8 @@ export const SubMenuMixin = (superClass) =>
31
31
  /**
32
32
  * Overriding the observer to not add global "contextmenu" listener.
33
33
  */
34
- _openedChanged(opened) {
35
- this._overlayElement.opened = opened;
34
+ _openedChanged() {
35
+ // Do nothing
36
36
  }
37
37
 
38
38
  /**
@@ -43,7 +43,7 @@ export const SubMenuMixin = (superClass) =>
43
43
 
44
44
  // Only handle 1st level submenu
45
45
  if (this.hasAttribute('is-root')) {
46
- this.getRootNode().host._close();
46
+ this.parentElement._close();
47
47
  }
48
48
  }
49
49
 
@@ -7,6 +7,7 @@ import './vaadin-menu-bar-item.js';
7
7
  import './vaadin-menu-bar-list-box.js';
8
8
  import './vaadin-menu-bar-overlay.js';
9
9
  import { css, html, LitElement } from 'lit';
10
+ import { ifDefined } from 'lit/directives/if-defined.js';
10
11
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
11
12
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
12
13
  import { ThemePropertyMixin } from '@vaadin/vaadin-themable-mixin/vaadin-theme-property-mixin.js';
@@ -40,17 +41,25 @@ class MenuBarSubmenu extends SubMenuMixin(ThemePropertyMixin(PolylitMixin(LitEle
40
41
 
41
42
  /** @protected */
42
43
  render() {
43
- return html`<slot id="slot"></slot>`;
44
- }
45
-
46
- /**
47
- * @protected
48
- * @override
49
- */
50
- createRenderRoot() {
51
- const root = super.createRenderRoot();
52
- root.appendChild(this._overlayElement);
53
- return root;
44
+ return html`
45
+ <vaadin-menu-bar-overlay
46
+ id="overlay"
47
+ .owner="${this}"
48
+ .opened="${this.opened}"
49
+ .model="${this._context}"
50
+ .modeless="${this._modeless}"
51
+ .renderer="${this.__itemsRenderer}"
52
+ .withBackdrop="${this._phone}"
53
+ ?phone="${this._phone}"
54
+ theme="${ifDefined(this._theme)}"
55
+ exportparts="backdrop, overlay, content"
56
+ @opened-changed="${this._onOverlayOpened}"
57
+ @vaadin-overlay-open="${this._onVaadinOverlayOpen}"
58
+ >
59
+ <slot name="overlay"></slot>
60
+ <slot name="submenu" slot="submenu"></slot>
61
+ </vaadin-menu-bar-overlay>
62
+ `;
54
63
  }
55
64
  }
56
65
 
@@ -30,13 +30,13 @@ export interface MenuBarEventMap<TItem extends MenuBarItem = MenuBarItem>
30
30
  *
31
31
  * To create the menu bar, first add the component to the page:
32
32
  *
33
- * ```
33
+ * ```html
34
34
  * <vaadin-menu-bar></vaadin-menu-bar>
35
35
  * ```
36
36
  *
37
37
  * And then use [`items`](#/elements/vaadin-menu-bar#property-items) property to initialize the structure:
38
38
  *
39
- * ```
39
+ * ```js
40
40
  * document.querySelector('vaadin-menu-bar').items = [{text: 'File'}, {text: 'Edit'}];
41
41
  * ```
42
42
  *
@@ -65,7 +65,7 @@ export interface MenuBarEventMap<TItem extends MenuBarItem = MenuBarItem>
65
65
  * - `<vaadin-menu-bar-button>` - has the same API as [`<vaadin-button>`](#/elements/vaadin-button).
66
66
  * - `<vaadin-menu-bar-item>` - has the same API as [`<vaadin-item>`](#/elements/vaadin-item).
67
67
  * - `<vaadin-menu-bar-list-box>` - has the same API as [`<vaadin-list-box>`](#/elements/vaadin-list-box).
68
- * - `<vaadin-menu-bar-overlay>` - has the same API as [`<vaadin-overlay>`](#/elements/vaadin-overlay).
68
+ * - `<vaadin-menu-bar-submenu>` - has the same API as [`<vaadin-context-menu>`](#/elements/vaadin-context-menu).
69
69
  *
70
70
  * The `<vaadin-menu-bar-item>` sub-menu elements have the following additional state attributes
71
71
  * on top of the built-in `<vaadin-item>` state attributes:
@@ -74,9 +74,6 @@ export interface MenuBarEventMap<TItem extends MenuBarItem = MenuBarItem>
74
74
  * ---------- |-------------
75
75
  * `expanded` | Expanded parent item.
76
76
  *
77
- * Note: the `theme` attribute value set on `<vaadin-menu-bar>` is
78
- * propagated to the internal components listed above.
79
- *
80
77
  * @fires {CustomEvent} item-selected - Fired when a submenu item or menu bar button without children is clicked.
81
78
  */
82
79
  declare class MenuBar<TItem extends MenuBarItem = MenuBarItem> extends HTMLElement {
@@ -5,12 +5,14 @@
5
5
  */
6
6
  import './vaadin-menu-bar-submenu.js';
7
7
  import './vaadin-menu-bar-button.js';
8
- import { css, html, LitElement } from 'lit';
8
+ import { html, LitElement } from 'lit';
9
9
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
10
10
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
11
11
  import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
12
12
  import { TooltipController } from '@vaadin/component-base/src/tooltip-controller.js';
13
+ import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js';
13
14
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
15
+ import { menuBarStyles } from './styles/vaadin-menu-bar-base-styles.js';
14
16
  import { MenuBarMixin } from './vaadin-menu-bar-mixin.js';
15
17
 
16
18
  /**
@@ -20,13 +22,13 @@ import { MenuBarMixin } from './vaadin-menu-bar-mixin.js';
20
22
  *
21
23
  * To create the menu bar, first add the component to the page:
22
24
  *
23
- * ```
25
+ * ```html
24
26
  * <vaadin-menu-bar></vaadin-menu-bar>
25
27
  * ```
26
28
  *
27
29
  * And then use [`items`](#/elements/vaadin-menu-bar#property-items) property to initialize the structure:
28
30
  *
29
- * ```
31
+ * ```js
30
32
  * document.querySelector('vaadin-menu-bar').items = [{text: 'File'}, {text: 'Edit'}];
31
33
  * ```
32
34
  *
@@ -55,7 +57,7 @@ import { MenuBarMixin } from './vaadin-menu-bar-mixin.js';
55
57
  * - `<vaadin-menu-bar-button>` - has the same API as [`<vaadin-button>`](#/elements/vaadin-button).
56
58
  * - `<vaadin-menu-bar-item>` - has the same API as [`<vaadin-item>`](#/elements/vaadin-item).
57
59
  * - `<vaadin-menu-bar-list-box>` - has the same API as [`<vaadin-list-box>`](#/elements/vaadin-list-box).
58
- * - `<vaadin-menu-bar-overlay>` - has the same API as [`<vaadin-overlay>`](#/elements/vaadin-overlay).
60
+ * - `<vaadin-menu-bar-submenu>` - has the same API as [`<vaadin-context-menu>`](#/elements/vaadin-context-menu).
59
61
  *
60
62
  * The `<vaadin-menu-bar-item>` sub-menu elements have the following additional state attributes
61
63
  * on top of the built-in `<vaadin-item>` state attributes:
@@ -64,9 +66,6 @@ import { MenuBarMixin } from './vaadin-menu-bar-mixin.js';
64
66
  * ---------- |-------------
65
67
  * `expanded` | Expanded parent item.
66
68
  *
67
- * Note: the `theme` attribute value set on `<vaadin-menu-bar>` is
68
- * propagated to the internal components listed above.
69
- *
70
69
  * @fires {CustomEvent<boolean>} item-selected - Fired when a submenu item or menu bar button without children is clicked.
71
70
  *
72
71
  * @customElement
@@ -75,39 +74,24 @@ import { MenuBarMixin } from './vaadin-menu-bar-mixin.js';
75
74
  * @mixes MenuBarMixin
76
75
  * @mixes ThemableMixin
77
76
  */
78
- class MenuBar extends MenuBarMixin(ElementMixin(ThemableMixin(PolylitMixin(LitElement)))) {
77
+ class MenuBar extends MenuBarMixin(ElementMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement))))) {
79
78
  static get is() {
80
79
  return 'vaadin-menu-bar';
81
80
  }
82
81
 
83
82
  static get styles() {
84
- return css`
85
- :host {
86
- display: block;
87
- }
88
-
89
- :host([hidden]) {
90
- display: none !important;
91
- }
92
-
93
- [part='container'] {
94
- position: relative;
95
- display: flex;
96
- width: 100%;
97
- flex-wrap: nowrap;
98
- overflow: hidden;
99
- }
100
- `;
83
+ return menuBarStyles;
101
84
  }
102
85
 
103
86
  /** @protected */
104
87
  render() {
105
88
  return html`
106
- <div part="container">
89
+ <div part="container" @click="${this.__onButtonClick}" @mouseover="${this._onMouseOver}">
107
90
  <slot></slot>
108
91
  <slot name="overflow"></slot>
109
92
  </div>
110
- <vaadin-menu-bar-submenu is-root .overlayClass="${this.overlayClass}"></vaadin-menu-bar-submenu>
93
+
94
+ <slot name="submenu"></slot>
111
95
 
112
96
  <slot name="tooltip"></slot>
113
97
  `;
@@ -1,2 +1,2 @@
1
- import './theme/lumo/vaadin-menu-bar.js';
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-alpha1",
4
+ "version": "25.0.0-alpha11",
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/25.0.0-alpha1/#/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/25.0.0-alpha1/#/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-alpha1/#/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-alpha1/#/elements/vaadin-list-box).\n- `<vaadin-menu-bar-overlay>` - has the same API as [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha1/#/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.",
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-alpha11/#/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-alpha11/#/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-alpha11/#/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-alpha11/#/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-alpha11/#/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",
@@ -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-alpha1",
4
+ "version": "25.0.0-alpha11",
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/25.0.0-alpha1/#/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/25.0.0-alpha1/#/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-alpha1/#/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-alpha1/#/elements/vaadin-list-box).\n- `<vaadin-menu-bar-overlay>` - has the same API as [`<vaadin-overlay>`](https://cdn.vaadin.com/vaadin-web-components/25.0.0-alpha1/#/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.",
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-alpha11/#/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-alpha11/#/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-alpha11/#/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-alpha11/#/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-alpha11/#/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
  {
@@ -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,2 +0,0 @@
1
- import './vaadin-menu-bar-button-styles.js';
2
- import '../../src/vaadin-menu-bar-button.js';
@@ -1,2 +0,0 @@
1
- import './vaadin-menu-bar-button-styles.js';
2
- import '../../src/vaadin-menu-bar-button.js';
@@ -1,2 +0,0 @@
1
- import '@vaadin/vaadin-lumo-styles/sizing.js';
2
- import '@vaadin/vaadin-lumo-styles/spacing.js';
@@ -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
- );
@@ -1,6 +0,0 @@
1
- import './vaadin-menu-bar-button.js';
2
- import './vaadin-menu-bar-item-styles.js';
3
- import './vaadin-menu-bar-list-box-styles.js';
4
- import './vaadin-menu-bar-overlay-styles.js';
5
- import './vaadin-menu-bar-styles.js';
6
- import '../../src/vaadin-menu-bar.js';
@@ -1,6 +0,0 @@
1
- import './vaadin-menu-bar-button.js';
2
- import './vaadin-menu-bar-item-styles.js';
3
- import './vaadin-menu-bar-list-box-styles.js';
4
- import './vaadin-menu-bar-overlay-styles.js';
5
- import './vaadin-menu-bar-styles.js';
6
- import '../../src/vaadin-menu-bar.js';