diff --git a/packages/menu-bar/src/vaadin-menu-bar-mixin.js b/packages/menu-bar/src/vaadin-menu-bar-mixin.js index 76154b503b..d7913f3230 100644 --- a/packages/menu-bar/src/vaadin-menu-bar-mixin.js +++ b/packages/menu-bar/src/vaadin-menu-bar-mixin.js @@ -883,6 +883,13 @@ export const MenuBarMixin = (superClass) => this._expandedButton = button; requestAnimationFrame(async () => { + // After changing items, buttons are recreated so the old button is + // no longer in the DOM. Reset position target to null to prevent + // overlay from closing due to target width / height equal to 0. + if (overlay.positionTarget && !overlay.positionTarget.isConnected) { + overlay.positionTarget = null; + } + button.dispatchEvent( new CustomEvent('opensubmenu', { detail: { diff --git a/packages/menu-bar/test/sub-menu.common.js b/packages/menu-bar/test/sub-menu.common.js index 42a366731d..94bbadedac 100644 --- a/packages/menu-bar/test/sub-menu.common.js +++ b/packages/menu-bar/test/sub-menu.common.js @@ -377,6 +377,22 @@ describe('sub-menu', () => { expect(subMenu.opened).to.be.true; }); + it('should reopen sub-menu after updating items', async () => { + buttons[0].click(); + await nextRender(); + + document.body.click(); + await nextRender(); + + menu.items = [menu.items[0]]; + await nextRender(); + + buttons = menu._buttons; + buttons[0].click(); + await nextRender(); + expect(subMenu.opened).to.be.true; + }); + it('should dispatch item-selected event on leaf button click', () => { const spy = sinon.spy(); menu.addEventListener('item-selected', spy);