From d6be7a4557209e219b5eb6dc5eb8bb1c44a8aac7 Mon Sep 17 00:00:00 2001 From: Serhii Kulykov Date: Tue, 9 Jul 2024 10:00:45 +0300 Subject: [PATCH] fix: only focus parent item if sub-menu contained focus (#7519) --- .../src/vaadin-contextmenu-items-mixin.js | 10 +++++++++- packages/context-menu/test/items.common.js | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/context-menu/src/vaadin-contextmenu-items-mixin.js b/packages/context-menu/src/vaadin-contextmenu-items-mixin.js index 438997fbcd..21f341e1aa 100644 --- a/packages/context-menu/src/vaadin-contextmenu-items-mixin.js +++ b/packages/context-menu/src/vaadin-contextmenu-items-mixin.js @@ -361,6 +361,10 @@ export const ItemsMixin = (superClass) => if (item) { const { children } = item._item; + // Check if the sub-menu was focused before closing it. + const child = subMenu._overlayElement.getFirstChild(); + const isSubmenuFocused = child && child.focused; + if (subMenu.items !== children) { subMenu.close(); } @@ -374,8 +378,12 @@ export const ItemsMixin = (superClass) => // Forward parent overlay class const { overlayClass } = this; this.__openSubMenu(subMenu, item, overlayClass); - } else { + } else if (isSubmenuFocused) { + // If the sub-menu item was focused, focus its parent item. subMenu.listenOn.focus(); + } else if (!this._listBox.focused) { + // Otherwise, focus the overlay part to handle arrow keys. + this._overlayElement.$.overlay.focus(); } } } diff --git a/packages/context-menu/test/items.common.js b/packages/context-menu/test/items.common.js index 8c97bbd67e..718a0557d7 100644 --- a/packages/context-menu/test/items.common.js +++ b/packages/context-menu/test/items.common.js @@ -261,6 +261,22 @@ describe('items', () => { expect(focusSpy.called).to.be.true; }); + (isTouch ? it.skip : it)('should focus overlay part on closing sub-menu without focused item', async () => { + const parent = getMenuItems(rootMenu)[3]; + await openMenu(parent); + const nonParent = getMenuItems(rootMenu)[1]; + const focusSpy = sinon.spy(rootOverlay.$.overlay, 'focus'); + await openMenu(nonParent); + expect(focusSpy.called).to.be.true; + }); + + (isTouch ? it.skip : it)('should not focus overlay part if the parent menu list-box has focus', async () => { + await openMenu(getMenuItems(rootMenu)[1]); + const focusSpy = sinon.spy(rootOverlay.$.overlay, 'focus'); + await openMenu(getMenuItems(rootMenu)[2]); + expect(focusSpy.called).to.be.false; + }); + it('should not close the menu if root item has keep open', () => { getMenuItems(rootMenu)[2].click(); expect(rootMenu.opened).to.be.true;