From 8fa3efa19b8c7f87bb10c21dca3f33d1c6e0cb21 Mon Sep 17 00:00:00 2001 From: Siarhei Lunski Date: Thu, 26 Feb 2026 15:54:32 +0100 Subject: [PATCH] fix(makeselectable): fix arrow key navigation for menus inside table --- .../table/__tests__/makeSelectable.test.js | 88 +++++++++++++++++++ src/components/table/makeSelectable.js | 4 +- 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/components/table/__tests__/makeSelectable.test.js b/src/components/table/__tests__/makeSelectable.test.js index 2eaf5c02dd..845e85a2cc 100644 --- a/src/components/table/__tests__/makeSelectable.test.js +++ b/src/components/table/__tests__/makeSelectable.test.js @@ -733,6 +733,25 @@ describe('components/table/makeSelectable', () => { testClassNamePreventsArrowNavigation(className, hotKey); }, ); + + test('should not set focus if element with role="menu" is rendered', () => { + const wrapper = getWrapper({ + selectedItems: ['a'], + }); + + jest.spyOn(document, 'querySelector').mockImplementation(selector => { + if (selector === '[role="menu"]') { + return document.createElement('div'); // mock element found + } + return null; + }); + + wrapper.setState({ focusedIndex: undefined }); + const instance = wrapper.instance(); + const shortcut = instance.getHotkeyConfigs().find(h => h.get('key') === hotKey); + shortcut.handler({ preventDefault: sandbox.stub() }); + expect(wrapper.state('focusedIndex')).toEqual(undefined); + }); }); describe('up', () => { @@ -766,6 +785,25 @@ describe('components/table/makeSelectable', () => { testClassNamePreventsArrowNavigation(className, hotKey); }, ); + + test('should not set focus if element with role="menu" is rendered', () => { + const wrapper = getWrapper({ + selectedItems: ['a'], + }); + + jest.spyOn(document, 'querySelector').mockImplementation(selector => { + if (selector === '[role="menu"]') { + return document.createElement('div'); + } + return null; + }); + + wrapper.setState({ focusedIndex: 1 }); + const instance = wrapper.instance(); + const shortcut = instance.getHotkeyConfigs().find(h => h.get('key') === hotKey); + shortcut.handler({ preventDefault: sandbox.stub() }); + expect(wrapper.state('focusedIndex')).toEqual(1); + }); }); describe('shift+down', () => { @@ -1418,6 +1456,56 @@ describe('components/table/makeSelectable', () => { }); }); + describe('isDropdownMenuOpen()', () => { + test('should return true when .dropdown-menu-element exists', () => { + const wrapper = getWrapper(); + const instance = wrapper.instance(); + + jest.spyOn(document, 'querySelector').mockImplementation(selector => { + if (selector === '.dropdown-menu-element') { + return document.createElement('div'); + } + return null; + }); + + expect(instance.isDropdownMenuOpen()).toBe(true); + }); + + test('should return true when element with role="menu" exists', () => { + const wrapper = getWrapper(); + const instance = wrapper.instance(); + + jest.spyOn(document, 'querySelector').mockImplementation(selector => { + if (selector === '[role="menu"]') { + return document.createElement('div'); + } + return null; + }); + + expect(instance.isDropdownMenuOpen()).toBe(true); + }); + + test('should return true when both .dropdown-menu-element and role="menu" exist', () => { + const wrapper = getWrapper(); + const instance = wrapper.instance(); + + jest.spyOn(document, 'querySelector').mockImplementation(() => { + return document.createElement('div'); + }); + + expect(instance.isDropdownMenuOpen()).toBe(true); + }); + + test('should return false when neither .dropdown-menu-element nor role="menu" exist', () => { + const wrapper = getWrapper(); + const instance = wrapper.instance(); + + jest.spyOn(document, 'querySelector').mockImplementation(() => null); + + expect(instance.isDropdownMenuOpen()).toBe(false); + }); + }); + describe('render()', () => { test('should add "is-selectable" class and pass props to table', () => { const wrapper = getWrapper({}); diff --git a/src/components/table/makeSelectable.js b/src/components/table/makeSelectable.js index e538b87ea0..7392d1913f 100644 --- a/src/components/table/makeSelectable.js +++ b/src/components/table/makeSelectable.js @@ -646,7 +646,9 @@ function makeSelectable(BaseTable) { isFlyoutOpen = () => document.querySelector('.flyout-overlay') !== null; - isDropdownMenuOpen = () => document.querySelector('.dropdown-menu-element') !== null; + isDropdownMenuOpen = () => + document.querySelector('.dropdown-menu-element') !== null || + document.querySelector('[role="menu"]') !== null; shouldNotAllowArrowKeyNavigation = event => this.isTargetQuickSearch(event) || this.isFlyoutOpen() || this.isDropdownMenuOpen();