@vaadin/menu-bar 25.3.0 → 25.4.0-alpha1

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.
@@ -50,9 +50,9 @@
50
50
  "name": "i18n",
51
51
  "privacy": "public",
52
52
  "type": {
53
- "text": "Object"
53
+ "text": "Object | undefined"
54
54
  },
55
- "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```",
55
+ "description": "The object used to localize this component. To change the default\nlocalization, set this to an object that provides all properties, or\njust the individual properties you want to change.\n\nWhen not set, defaults to `undefined`.\n\nThe object has the following JSON structure and default values:\n```js\n{\n moreOptions: 'More options'\n}\n```",
56
56
  "attribute": "i18n",
57
57
  "inheritedFrom": {
58
58
  "name": "I18nMixin",
@@ -124,9 +124,9 @@
124
124
  {
125
125
  "name": "i18n",
126
126
  "type": {
127
- "text": "Object"
127
+ "text": "Object | undefined"
128
128
  },
129
- "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\nShould be overridden by subclasses to provide a custom JSDoc with the\ndefault I18N properties.",
129
+ "description": "The object used to localize this component. To change the default\nlocalization, set this to an object that provides all properties, or\njust the individual properties you want to change.\n\nWhen not set, defaults to `undefined`.\n\nShould be overridden by subclasses to provide a custom JSDoc with the\ndefault I18N properties.",
130
130
  "fieldName": "i18n",
131
131
  "inheritedFrom": {
132
132
  "name": "I18nMixin",
@@ -334,9 +334,9 @@
334
334
  "name": "i18n",
335
335
  "privacy": "public",
336
336
  "type": {
337
- "text": "Object"
337
+ "text": "Object | undefined"
338
338
  },
339
- "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```",
339
+ "description": "The object used to localize this component. To change the default\nlocalization, set this to an object that provides all properties, or\njust the individual properties you want to change.\n\nWhen not set, defaults to `undefined`.\n\nThe object has the following JSON structure and default values:\n```js\n{\n moreOptions: 'More options'\n}\n```",
340
340
  "attribute": "i18n",
341
341
  "inheritedFrom": {
342
342
  "name": "I18nMixin",
@@ -429,9 +429,9 @@
429
429
  {
430
430
  "name": "i18n",
431
431
  "type": {
432
- "text": "Object"
432
+ "text": "Object | undefined"
433
433
  },
434
- "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\nShould be overridden by subclasses to provide a custom JSDoc with the\ndefault I18N properties.",
434
+ "description": "The object used to localize this component. To change the default\nlocalization, set this to an object that provides all properties, or\njust the individual properties you want to change.\n\nWhen not set, defaults to `undefined`.\n\nShould be overridden by subclasses to provide a custom JSDoc with the\ndefault I18N properties.",
435
435
  "fieldName": "i18n",
436
436
  "inheritedFrom": {
437
437
  "name": "I18nMixin",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/menu-bar",
3
- "version": "25.3.0",
3
+ "version": "25.4.0-alpha1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -35,23 +35,23 @@
35
35
  ],
36
36
  "dependencies": {
37
37
  "@open-wc/dedupe-mixin": "^1.3.0",
38
- "@vaadin/a11y-base": "~25.3.0",
39
- "@vaadin/button": "~25.3.0",
40
- "@vaadin/component-base": "~25.3.0",
41
- "@vaadin/context-menu": "~25.3.0",
42
- "@vaadin/item": "~25.3.0",
43
- "@vaadin/list-box": "~25.3.0",
44
- "@vaadin/overlay": "~25.3.0",
45
- "@vaadin/vaadin-themable-mixin": "~25.3.0",
38
+ "@vaadin/a11y-base": "25.4.0-alpha1",
39
+ "@vaadin/button": "25.4.0-alpha1",
40
+ "@vaadin/component-base": "25.4.0-alpha1",
41
+ "@vaadin/context-menu": "25.4.0-alpha1",
42
+ "@vaadin/item": "25.4.0-alpha1",
43
+ "@vaadin/list-box": "25.4.0-alpha1",
44
+ "@vaadin/overlay": "25.4.0-alpha1",
45
+ "@vaadin/vaadin-themable-mixin": "25.4.0-alpha1",
46
46
  "lit": "^3.0.0"
47
47
  },
48
48
  "devDependencies": {
49
- "@vaadin/aura": "~25.3.0",
50
- "@vaadin/chai-plugins": "~25.3.0",
51
- "@vaadin/icon": "~25.3.0",
52
- "@vaadin/test-runner-commands": "~25.3.0",
49
+ "@vaadin/aura": "25.4.0-alpha1",
50
+ "@vaadin/chai-plugins": "25.4.0-alpha1",
51
+ "@vaadin/icon": "25.4.0-alpha1",
52
+ "@vaadin/test-runner-commands": "25.4.0-alpha1",
53
53
  "@vaadin/testing-helpers": "^2.0.0",
54
- "@vaadin/vaadin-lumo-styles": "~25.3.0",
54
+ "@vaadin/vaadin-lumo-styles": "25.4.0-alpha1",
55
55
  "sinon": "^22.0.0"
56
56
  },
57
57
  "customElements": "custom-elements.json",
@@ -59,5 +59,5 @@
59
59
  "web-types.json",
60
60
  "web-types.lit.json"
61
61
  ],
62
- "gitHead": "4133747243c03bf544f6e82cc2ec9f295aaccd65"
62
+ "gitHead": "be38ec1866e96508f3f4591f95c949ef55903a34"
63
63
  }
@@ -158,9 +158,11 @@ export declare class MenuBarMixinClass<TItem extends MenuBarItem = MenuBarItem>
158
158
 
159
159
  /**
160
160
  * The object used to localize this component. To change the default
161
- * localization, replace this with an object that provides all properties, or
161
+ * localization, set this to an object that provides all properties, or
162
162
  * just the individual properties you want to change.
163
163
  *
164
+ * When not set, defaults to `undefined`.
165
+ *
164
166
  * The object has the following JSON structure and default values:
165
167
  * ```js
166
168
  * {
@@ -168,7 +170,7 @@ export declare class MenuBarMixinClass<TItem extends MenuBarItem = MenuBarItem>
168
170
  * }
169
171
  * ```
170
172
  */
171
- i18n: MenuBarI18n;
173
+ i18n: MenuBarI18n | undefined;
172
174
 
173
175
  /**
174
176
  * If true, the submenu will open on hover (mouseover) instead of click.
@@ -57,6 +57,9 @@ const DEFAULT_I18N = {
57
57
  moreOptions: 'More options',
58
58
  };
59
59
 
60
+ // Two client rects of the same edge can differ by float noise, a few 1e-5 px under browser zoom
61
+ const OVERFLOW_TOLERANCE = 0.1;
62
+
60
63
  export const MenuBarMixin = (superClass) =>
61
64
  class MenuBarMixinClass extends I18nMixin(
62
65
  KeyboardDirectionMixin(ResizeMixin(FocusMixin(DisabledMixin(superClass)))),
@@ -203,16 +206,18 @@ export const MenuBarMixin = (superClass) =>
203
206
 
204
207
  /**
205
208
  * The object used to localize this component. To change the default
206
- * localization, replace this with an object that provides all properties, or
209
+ * localization, set this to an object that provides all properties, or
207
210
  * just the individual properties you want to change.
208
211
  *
212
+ * When not set, defaults to `undefined`.
213
+ *
209
214
  * The object has the following JSON structure and default values:
210
215
  * ```js
211
216
  * {
212
217
  * moreOptions: 'More options'
213
218
  * }
214
219
  * ```
215
- * @type {!MenuBarI18n}
220
+ * @type {MenuBarI18n | undefined}
216
221
  */
217
222
  get i18n() {
218
223
  return super.i18n;
@@ -484,49 +489,110 @@ export const MenuBarMixin = (superClass) =>
484
489
  this._hasOverflow = items.length > 0;
485
490
  }
486
491
 
487
- /** @private */
488
- __setOverflowItems(buttons, overflow) {
489
- const container = this._container;
492
+ /**
493
+ * Inline end edge of the element, mirrored in RTL. Unlike `offsetWidth` and `scrollWidth`,
494
+ * the rect keeps the fraction that browser zoom leaves on the width.
495
+ *
496
+ * @param {!HTMLElement} el
497
+ * @return {number}
498
+ * @private
499
+ */
500
+ __getInlineEnd(el) {
501
+ const { left, right } = el.getBoundingClientRect();
502
+ return this.__isRTL ? -left : right;
503
+ }
490
504
 
491
- // Prevent the container from shrinking while buttons are being hidden.
492
- // The host has min-width: 0 so it can shrink inside flex/grid layouts.
493
- // Without this lock, hiding a button reduces the host width, which
494
- // shrinks the container (width: 100%), shifting all button positions
495
- // and causing a cascading collapse where every button appears to overflow.
496
- container.style.minWidth = `${container.offsetWidth}px`;
505
+ /**
506
+ * Positions of the buttons, read in one batch before any of them is hidden.
507
+ * Mirrored in RTL so that a larger value is always further along the inline axis.
508
+ *
509
+ * @typedef {object} MenuBarOverflowLayout
510
+ * @property {number[]} starts Inline start of each button
511
+ * @property {number[]} ends Inline end of each button
512
+ * @property {number[]} margins Inline start margin of each button
513
+ * @property {number} overflowExtent Space the overflow button adds after the last button
514
+ */
497
515
 
498
- if (container.offsetWidth < container.scrollWidth) {
499
- this._hasOverflow = true;
516
+ /**
517
+ * @param {!Array<!HTMLElement>} buttons
518
+ * @param {!HTMLElement} overflow
519
+ * @return {!MenuBarOverflowLayout}
520
+ * @private
521
+ */
522
+ __measureButtons(buttons, overflow) {
523
+ const isRTL = this.__isRTL;
524
+ const rects = buttons.map((btn) => btn.getBoundingClientRect());
525
+ const ends = rects.map(({ left, right }) => (isRTL ? -left : right));
500
526
 
501
- const isRTL = this.__isRTL;
502
- const containerLeft = container.offsetLeft;
503
- const containerWidth = container.offsetWidth;
527
+ return {
528
+ starts: rects.map(({ left, right }) => (isRTL ? -right : left)),
529
+ ends,
530
+ // `auto` resolves to 0 while the content overflows.
531
+ margins: buttons.map((btn) => parseFloat(getComputedStyle(btn).marginInlineStart) || 0),
532
+ overflowExtent: this.__getInlineEnd(overflow) - ends.at(-1),
533
+ };
534
+ }
504
535
 
505
- const remaining = [...buttons];
506
- while (remaining.length) {
507
- // The overflow button follows the last remaining one, so its far edge is what has
508
- // to fit. Auto margins move the whole row but cannot push that edge past the end.
509
- const overflowEnd = isRTL
510
- ? containerWidth - (overflow.offsetLeft - containerLeft)
511
- : overflow.offsetLeft + overflow.offsetWidth - containerLeft;
536
+ /**
537
+ * Picks the buttons to collapse so that the rest plus the overflow button end inside
538
+ * the container. Hiding a button only shifts the buttons after it, so the end of any
539
+ * kept range follows from one measurement.
540
+ *
541
+ * @param {!Array<!HTMLElement>} buttons
542
+ * @param {!MenuBarOverflowLayout} layout
543
+ * @param {number} containerWidth
544
+ * @return {!Array<!HTMLElement>} buttons to collapse, in DOM order
545
+ * @private
546
+ */
547
+ __getCollapsedButtons(buttons, { starts, ends, margins, overflowExtent }, containerWidth) {
548
+ let lo = 0;
549
+ let hi = buttons.length - 1;
550
+
551
+ // The first kept button keeps its own start margin in front of the range.
552
+ while (lo <= hi && margins[lo] + ends[hi] - starts[lo] + overflowExtent > containerWidth + OVERFLOW_TOLERANCE) {
553
+ if (this.reverseCollapse) {
554
+ lo += 1;
555
+ } else {
556
+ hi -= 1;
557
+ }
558
+ }
512
559
 
513
- if (overflowEnd <= containerWidth) {
514
- break;
515
- }
560
+ return buttons.filter((_, i) => i < lo || i > hi);
561
+ }
516
562
 
517
- const btn = this.reverseCollapse ? remaining.shift() : remaining.pop();
563
+ /** @private */
564
+ __setOverflowItems(buttons, overflow) {
565
+ const container = this._container;
566
+ // Read before any write, so a menu bar that fits forces no layout
567
+ const width = container.offsetWidth;
568
+ const lastButton = buttons.at(-1);
569
+
570
+ if (lastButton && this.__getInlineEnd(lastButton) > this.__getInlineEnd(container) + OVERFLOW_TOLERANCE) {
571
+ // Prevent the container from shrinking while buttons are being hidden.
572
+ // The host has min-width: 0 so it can shrink inside flex/grid layouts.
573
+ // Without this lock, hiding a button reduces the host width, which
574
+ // shrinks the container (width: 100%), shifting all button positions
575
+ // and causing a cascading collapse where every button appears to overflow.
576
+ container.style.minWidth = `${width}px`;
577
+ this._hasOverflow = true;
518
578
 
519
- // Save width for buttons with component
520
- btn.style.width = getComputedStyle(btn).width;
579
+ // Read the layout once the overflow button is in flow
580
+ const layout = this.__measureButtons(buttons, overflow);
581
+ const containerWidth = container.getBoundingClientRect().width;
582
+ const collapsed = this.__getCollapsedButtons(buttons, layout, containerWidth);
583
+ // Read button widths once outside of the loop to avoid repetitive layout
584
+ const widths = collapsed.map((btn) => getComputedStyle(btn).width);
585
+
586
+ // Write the DOM state
587
+ collapsed.forEach((btn, i) => {
588
+ btn.style.width = widths[i];
521
589
  btn.style.visibility = 'hidden';
522
590
  btn.style.position = 'absolute';
523
- }
591
+ });
592
+ this.__updateOverflow(collapsed.map((btn) => btn.item));
524
593
 
525
- const items = buttons.filter((b) => !remaining.includes(b)).map((b) => b.item);
526
- this.__updateOverflow(items);
594
+ container.style.minWidth = '';
527
595
  }
528
-
529
- container.style.minWidth = '';
530
596
  }
531
597
 
532
598
  /** @private */
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.3.0",
4
+ "version": "25.4.0-alpha1",
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.3.0/#/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\nThe following custom CSS properties are available for styling:\n\nCustom CSS property |\n:---------------------------|\n| `--vaadin-menu-bar-gap` |\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.3.0/#/elements/vaadin-button).\n- `<vaadin-menu-bar-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.3.0/#/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.3.0/#/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.3.0/#/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.",
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.4.0-alpha1/#/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\nThe following custom CSS properties are available for styling:\n\nCustom CSS property |\n:---------------------------|\n| `--vaadin-menu-bar-gap` |\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.4.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.4.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.4.0-alpha1/#/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.4.0-alpha1/#/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",
@@ -69,10 +69,11 @@
69
69
  },
70
70
  {
71
71
  "name": "i18n",
72
- "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```",
72
+ "description": "The object used to localize this component. To change the default\nlocalization, set this to an object that provides all properties, or\njust the individual properties you want to change.\n\nWhen not set, defaults to `undefined`.\n\nThe object has the following JSON structure and default values:\n```js\n{\n moreOptions: 'More options'\n}\n```",
73
73
  "value": {
74
74
  "type": [
75
- "Object"
75
+ "Object",
76
+ "undefined"
76
77
  ]
77
78
  }
78
79
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/menu-bar",
4
- "version": "25.3.0",
4
+ "version": "25.4.0-alpha1",
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.3.0/#/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\nThe following custom CSS properties are available for styling:\n\nCustom CSS property |\n:---------------------------|\n| `--vaadin-menu-bar-gap` |\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.3.0/#/elements/vaadin-button).\n- `<vaadin-menu-bar-item>` - has the same API as [`<vaadin-item>`](https://cdn.vaadin.com/vaadin-web-components/25.3.0/#/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.3.0/#/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.3.0/#/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.",
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.4.0-alpha1/#/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\nThe following custom CSS properties are available for styling:\n\nCustom CSS property |\n:---------------------------|\n| `--vaadin-menu-bar-gap` |\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.4.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.4.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.4.0-alpha1/#/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.4.0-alpha1/#/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
  {
@@ -28,7 +28,7 @@
28
28
  },
29
29
  {
30
30
  "name": ".i18n",
31
- "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```",
31
+ "description": "The object used to localize this component. To change the default\nlocalization, set this to an object that provides all properties, or\njust the individual properties you want to change.\n\nWhen not set, defaults to `undefined`.\n\nThe object has the following JSON structure and default values:\n```js\n{\n moreOptions: 'More options'\n}\n```",
32
32
  "value": {
33
33
  "kind": "expression"
34
34
  }