@vaadin/menu-bar 25.4.0-dev.55bb86e155 → 25.4.0-dev.c9532cd333

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/menu-bar",
3
- "version": "25.4.0-dev.55bb86e155",
3
+ "version": "25.4.0-dev.c9532cd333",
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.4.0-dev.55bb86e155",
39
- "@vaadin/button": "25.4.0-dev.55bb86e155",
40
- "@vaadin/component-base": "25.4.0-dev.55bb86e155",
41
- "@vaadin/context-menu": "25.4.0-dev.55bb86e155",
42
- "@vaadin/item": "25.4.0-dev.55bb86e155",
43
- "@vaadin/list-box": "25.4.0-dev.55bb86e155",
44
- "@vaadin/overlay": "25.4.0-dev.55bb86e155",
45
- "@vaadin/vaadin-themable-mixin": "25.4.0-dev.55bb86e155",
38
+ "@vaadin/a11y-base": "25.4.0-dev.c9532cd333",
39
+ "@vaadin/button": "25.4.0-dev.c9532cd333",
40
+ "@vaadin/component-base": "25.4.0-dev.c9532cd333",
41
+ "@vaadin/context-menu": "25.4.0-dev.c9532cd333",
42
+ "@vaadin/item": "25.4.0-dev.c9532cd333",
43
+ "@vaadin/list-box": "25.4.0-dev.c9532cd333",
44
+ "@vaadin/overlay": "25.4.0-dev.c9532cd333",
45
+ "@vaadin/vaadin-themable-mixin": "25.4.0-dev.c9532cd333",
46
46
  "lit": "^3.0.0"
47
47
  },
48
48
  "devDependencies": {
49
- "@vaadin/aura": "25.4.0-dev.55bb86e155",
50
- "@vaadin/chai-plugins": "25.4.0-dev.55bb86e155",
51
- "@vaadin/icon": "25.4.0-dev.55bb86e155",
52
- "@vaadin/test-runner-commands": "25.4.0-dev.55bb86e155",
49
+ "@vaadin/aura": "25.4.0-dev.c9532cd333",
50
+ "@vaadin/chai-plugins": "25.4.0-dev.c9532cd333",
51
+ "@vaadin/icon": "25.4.0-dev.c9532cd333",
52
+ "@vaadin/test-runner-commands": "25.4.0-dev.c9532cd333",
53
53
  "@vaadin/testing-helpers": "^2.0.0",
54
- "@vaadin/vaadin-lumo-styles": "25.4.0-dev.55bb86e155",
54
+ "@vaadin/vaadin-lumo-styles": "25.4.0-dev.c9532cd333",
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": "5db8e58fb088121b067290b0ed90d12d7d4084f2"
62
+ "gitHead": "1fbf460cf3602f011721b6ed7d98961d1c1bf85e"
63
63
  }
@@ -15,6 +15,12 @@ export const menuBarStyles = css`
15
15
  display: none !important;
16
16
  }
17
17
 
18
+ /* Keep the width measured with all buttons in flow while the host is frozen */
19
+ :host([overflow-frozen]) {
20
+ contain: inline-size !important;
21
+ contain-intrinsic-inline-size: var(--_vaadin-menu-bar-content-width);
22
+ }
23
+
18
24
  [part='container'] {
19
25
  display: flex;
20
26
  flex-wrap: nowrap;
@@ -464,7 +464,6 @@ export const MenuBarMixin = (superClass) =>
464
464
  buttons.forEach((button) => {
465
465
  button.style.visibility = '';
466
466
  button.style.position = '';
467
- button.style.width = '';
468
467
 
469
468
  // Teleport item component back from "overflow" sub-menu
470
469
  const item = button.item?.component;
@@ -529,8 +528,9 @@ export const MenuBarMixin = (superClass) =>
529
528
  }
530
529
 
531
530
  /**
532
- * Positions of the buttons, read in one batch before any of them is hidden.
533
- * Mirrored in RTL so that a larger value is always further along the inline axis.
531
+ * Layout of the buttons, the overflow button and the container, read in one batch
532
+ * before any button is hidden. Positions are mirrored in RTL so that a larger value
533
+ * is always further along the inline axis.
534
534
  *
535
535
  * @typedef {object} MenuBarOverflowLayout
536
536
  * @property {number[]} starts Inline start of each button
@@ -538,6 +538,7 @@ export const MenuBarMixin = (superClass) =>
538
538
  * @property {number[]} margins Inline start margin of each button
539
539
  * @property {number} overflowExtent Space the overflow button adds after the last button
540
540
  * @property {number} containerWidth Width of the container
541
+ * @property {number} contentWidth Width of all buttons and the overflow button in flow
541
542
  */
542
543
 
543
544
  /**
@@ -546,18 +547,22 @@ export const MenuBarMixin = (superClass) =>
546
547
  * @return {!MenuBarOverflowLayout}
547
548
  * @private
548
549
  */
549
- __measureButtons(buttons, overflow) {
550
+ __getOverflowLayout(buttons, overflow) {
550
551
  const isRTL = this.__isRTL;
551
552
  const rects = buttons.map((btn) => btn.getBoundingClientRect());
552
553
  const ends = rects.map(({ left, right }) => (isRTL ? -left : right));
554
+ const overflowEnd = this.__getInlineEnd(overflow);
555
+ const containerRect = this._container.getBoundingClientRect();
556
+ const containerStart = isRTL ? -containerRect.right : containerRect.left;
553
557
 
554
558
  return {
555
559
  starts: rects.map(({ left, right }) => (isRTL ? -right : left)),
556
560
  ends,
557
561
  // `auto` resolves to 0 while the content overflows.
558
562
  margins: buttons.map((btn) => parseFloat(getComputedStyle(btn).marginInlineStart) || 0),
559
- overflowExtent: this.__getInlineEnd(overflow) - ends.at(-1),
560
- containerWidth: this._container.getBoundingClientRect().width,
563
+ overflowExtent: overflowEnd - ends.at(-1),
564
+ containerWidth: containerRect.width,
565
+ contentWidth: overflowEnd - containerStart,
561
566
  };
562
567
  }
563
568
 
@@ -588,30 +593,32 @@ export const MenuBarMixin = (superClass) =>
588
593
  }
589
594
 
590
595
  /**
591
- * Hides the buttons that do not fit next to the overflow button.
596
+ * Keeps the intrinsic width of the host at the given value. A parent sized by content,
597
+ * such as a split layout pane, shrinks the host once the buttons are out of flow. The
598
+ * width the host had with all buttons in flow keeps the collapse that was decided for it.
599
+ * The `overflow-frozen` attribute marks the frozen state for the styles and for the next
600
+ * detection. It is internal and not documented.
592
601
  *
593
- * @param {!Array<!HTMLElement>} buttons
594
- * @param {!MenuBarOverflowLayout} layout
595
- * @return {!Array<!HTMLElement>} hidden buttons, in DOM order
602
+ * @param {number} width
596
603
  * @private
597
604
  */
598
- __collapseButtons(buttons, layout) {
599
- const collapsed = this.__getButtonsToCollapse(buttons, layout);
600
- // Read button widths once outside of the loop to avoid repetitive layout
601
- const widths = collapsed.map((btn) => getComputedStyle(btn).width);
605
+ __freezeWidth(width) {
606
+ this.style.setProperty('--_vaadin-menu-bar-content-width', `${width}px`);
607
+ this.setAttribute('overflow-frozen', '');
608
+ }
602
609
 
603
- // Write the DOM state
604
- collapsed.forEach((btn, i) => {
605
- btn.style.width = widths[i];
606
- btn.style.visibility = 'hidden';
607
- btn.style.position = 'absolute';
608
- });
609
- return collapsed;
610
+ /** @private */
611
+ __unfreezeWidth() {
612
+ this.style.removeProperty('--_vaadin-menu-bar-content-width');
613
+ this.removeAttribute('overflow-frozen');
610
614
  }
611
615
 
612
616
  /**
613
617
  * Shows the overflow button and collapses buttons into it when the last button
614
- * does not fit in the container.
618
+ * does not fit in the container. Freezes the host width when the parent shrinks
619
+ * the host after the collapse. A frozen host stays frozen until all buttons and the
620
+ * overflow button fit, so that its flex basis does not change between detections
621
+ * when another element in the same row depends on it.
615
622
  *
616
623
  * @param {!Array<!HTMLElement>} buttons
617
624
  * @param {!HTMLElement} overflow
@@ -619,15 +626,31 @@ export const MenuBarMixin = (superClass) =>
619
626
  */
620
627
  __setOverflowItems(buttons, overflow) {
621
628
  const lastButton = buttons.at(-1);
622
- if (!lastButton || !this.__isPastContainerEnd(lastButton)) {
629
+ // A frozen host is as wide as all buttons plus the overflow button, so the quick
630
+ // check would report a fit one overflow button too early. Measure instead.
631
+ const wasFrozen = this.hasAttribute('overflow-frozen');
632
+ if (!lastButton || (!wasFrozen && !this.__isPastContainerEnd(lastButton))) {
633
+ this.__unfreezeWidth();
623
634
  return;
624
635
  }
625
636
  this._hasOverflow = true;
626
637
 
627
638
  // Read the layout once the overflow button is in flow
628
- const layout = this.__measureButtons(buttons, overflow);
629
- const collapsed = this.__collapseButtons(buttons, layout);
639
+ const layout = this.__getOverflowLayout(buttons, overflow);
640
+ const collapsed = this.__getButtonsToCollapse(buttons, layout);
641
+
642
+ // Write the DOM state
643
+ collapsed.forEach((btn) => {
644
+ btn.style.visibility = 'hidden';
645
+ btn.style.position = 'absolute';
646
+ });
630
647
  this.__updateOverflow(collapsed.map((btn) => btn.item));
648
+
649
+ if (collapsed.length === 0) {
650
+ this.__unfreezeWidth();
651
+ } else if (wasFrozen || this.__isPastContainerEnd(overflow)) {
652
+ this.__freezeWidth(layout.contentWidth);
653
+ }
631
654
  }
632
655
 
633
656
  /** @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.4.0-dev.55bb86e155",
4
+ "version": "25.4.0-dev.c9532cd333",
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.4.0-dev.55bb86e155/#/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-overflow` | Set when one or more buttons are collapsed into the overflow sub-menu\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-dev.55bb86e155/#/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-dev.55bb86e155/#/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-dev.55bb86e155/#/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-dev.55bb86e155/#/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-dev.c9532cd333/#/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-overflow` | Set when one or more buttons are collapsed into the overflow sub-menu\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-dev.c9532cd333/#/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-dev.c9532cd333/#/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-dev.c9532cd333/#/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-dev.c9532cd333/#/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.4.0-dev.55bb86e155",
4
+ "version": "25.4.0-dev.c9532cd333",
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.4.0-dev.55bb86e155/#/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-overflow` | Set when one or more buttons are collapsed into the overflow sub-menu\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-dev.55bb86e155/#/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-dev.55bb86e155/#/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-dev.55bb86e155/#/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-dev.55bb86e155/#/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-dev.c9532cd333/#/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-overflow` | Set when one or more buttons are collapsed into the overflow sub-menu\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-dev.c9532cd333/#/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-dev.c9532cd333/#/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-dev.c9532cd333/#/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-dev.c9532cd333/#/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
  {