From b08ab64539f3c8befcee6b83b6aa8187558726cb Mon Sep 17 00:00:00 2001 From: Vaadin Bot Date: Thu, 14 Mar 2024 08:38:52 +0100 Subject: [PATCH] fix: reset tabindex to -1 when initializing menu item (#7203) (#7208) Co-authored-by: Serhii Kulykov --- .../src/vaadin-contextmenu-items-mixin.js | 1 + packages/context-menu/test/items.common.js | 40 +++++++++++++++++++ packages/menu-bar/test/sub-menu.test.js | 31 +++++++++++++- 3 files changed, 71 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 2dc80e6494..0ed549d97f 100644 --- a/packages/context-menu/src/vaadin-contextmenu-items-mixin.js +++ b/packages/context-menu/src/vaadin-contextmenu-items-mixin.js @@ -178,6 +178,7 @@ export const ItemsMixin = (superClass) => // Support menu-bar / context-menu item if (component._hasVaadinItemMixin) { component.setAttribute('role', 'menuitem'); + component.tabIndex = -1; } if (component.localName === 'hr') { diff --git a/packages/context-menu/test/items.common.js b/packages/context-menu/test/items.common.js index 145aa36f69..6148764bf0 100644 --- a/packages/context-menu/test/items.common.js +++ b/packages/context-menu/test/items.common.js @@ -22,6 +22,12 @@ import { getMenuItems, getSubMenu, openMenu } from './helpers.js'; describe('items', () => { let rootMenu, subMenu, target, rootOverlay, subOverlay1; + const createComponent = (text) => { + const item = document.createElement('vaadin-context-menu-item'); + item.textContent = text; + return item; + }; + beforeEach(async () => { rootMenu = fixtureSync(` @@ -43,6 +49,14 @@ describe('items', () => { }, { text: 'foo-1' }, { text: 'foo-2', keepOpen: true }, + { + text: 'foo-3', + children: [ + { component: createComponent('foo-3-0') }, + { component: createComponent('foo-3-1') }, + { component: createComponent('foo-3-2') }, + ], + }, ]; await nextRender(); await openMenu(target); @@ -374,6 +388,32 @@ describe('items', () => { expect(spy.calledOnce).to.be.true; }); + it('should focus first item after re-opening when using components', async () => { + subMenu.close(); + rootOverlay.focus(); + + const rootItem = getMenuItems(rootMenu)[3]; + + // Open the sub-menu with item components + await openMenu(rootItem); + const subMenu2 = getSubMenu(rootMenu); + const items = getMenuItems(subMenu2); + + // Arrow Down to focus next item + items[0].focus(); + arrowDownKeyDown(items[0]); + expect(items[1].hasAttribute('focus-ring')).to.be.true; + + // Arrow Left to close the sub-menu + arrowLeftKeyDown(items[1]); + await nextFrame(); + expect(rootItem.hasAttribute('focus-ring')).to.be.true; + + // Re-open sub-menu and check focus + await openMenu(rootItem); + expect(items[0].hasAttribute('focus-ring')).to.be.true; + }); + it('should have modeless sub menus', () => { const rootItemRect = getMenuItems(rootMenu)[0].getBoundingClientRect(); const element = document.elementFromPoint(rootItemRect.left, rootItemRect.top); diff --git a/packages/menu-bar/test/sub-menu.test.js b/packages/menu-bar/test/sub-menu.test.js index b468b718e9..7ffe2d6d74 100644 --- a/packages/menu-bar/test/sub-menu.test.js +++ b/packages/menu-bar/test/sub-menu.test.js @@ -29,6 +29,12 @@ const menuOpenEvent = isTouch ? 'click' : 'mouseover'; describe('sub-menu', () => { let menu, buttons, subMenu, subMenuOverlay, item; + const createComponent = (text) => { + const item = document.createElement('vaadin-menu-bar-item'); + item.textContent = text; + return item; + }; + beforeEach(async () => { menu = fixtureSync(''); menu.items = [ @@ -45,7 +51,14 @@ describe('sub-menu', () => { { text: 'Menu Item 2' }, { text: 'Menu Item 3', - children: [{ text: 'Menu Item 3 1' }, { text: 'Menu Item 3 2' }], + children: [ + { + component: createComponent('Menu Item 3 1'), + }, + { + component: createComponent('Menu Item 3 2'), + }, + ], }, ]; await nextRender(menu); @@ -152,6 +165,22 @@ describe('sub-menu', () => { expect(spy.calledOnce).to.be.true; }); + it('should focus first item after re-opening when using components', async () => { + arrowDown(buttons[2]); + await nextRender(subMenu); + + const items = subMenuOverlay.querySelectorAll('vaadin-menu-bar-item'); + arrowDown(items[0]); + expect(items[1].hasAttribute('focus-ring')).to.be.true; + + // Close and re-open + esc(items[1]); + arrowDown(buttons[2]); + await nextRender(subMenu); + + expect(items[0].hasAttribute('focus-ring')).to.be.true; + }); + it('should close sub-menu on first item arrow up', async () => { arrowDown(buttons[0]); await oneEvent(subMenu, 'opened-changed');