From 00eb6b9f515ed0aa1c4fda00eaac73cd19be81b1 Mon Sep 17 00:00:00 2001 From: Mateusz Groth <39166248+MateuszGroth@users.noreply.github.com> Date: Fri, 30 Aug 2024 16:27:28 +0200 Subject: [PATCH] [material-ui][MenuList] Do not react to an event with modifier key pressed (#43505) Co-authored-by: ZeeshanTamboli --- .../mui-material/src/MenuList/MenuList.js | 10 +++++ .../test/integration/MenuList.test.js | 43 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/packages/mui-material/src/MenuList/MenuList.js b/packages/mui-material/src/MenuList/MenuList.js index dcb0a4efa03f03..595c4849c5ce45 100644 --- a/packages/mui-material/src/MenuList/MenuList.js +++ b/packages/mui-material/src/MenuList/MenuList.js @@ -144,6 +144,16 @@ const MenuList = React.forwardRef(function MenuList(props, ref) { const handleKeyDown = (event) => { const list = listRef.current; const key = event.key; + const isModifierKeyPressed = event.ctrlKey || event.metaKey || event.altKey; + + if (isModifierKeyPressed) { + if (onKeyDown) { + onKeyDown(event); + } + + return; + } + /** * @type {Element} - will always be defined since we are in a keydown handler * attached to an element. A keydown event is either dispatched to the activeElement diff --git a/packages/mui-material/test/integration/MenuList.test.js b/packages/mui-material/test/integration/MenuList.test.js index 66b5ab27c4862a..8e362f22c3168e 100644 --- a/packages/mui-material/test/integration/MenuList.test.js +++ b/packages/mui-material/test/integration/MenuList.test.js @@ -180,6 +180,49 @@ describe(' integration', () => { expect(menuitems[1]).to.have.property('tabIndex', -1); expect(menuitems[2]).to.have.property('tabIndex', -1); }); + + describe('when a modifier key is pressed', () => { + it('should not move the focus', () => { + const { getAllByRole } = render( + + Menu Item 1 + Menu Item 2 + Menu Item 3 + , + ); + + const menuitems = getAllByRole('menuitem'); + fireEvent.keyDown(menuitems[0], { key: 'ArrowDown', ctrlKey: true }); + expect(menuitems[0]).toHaveFocus(); + expect(menuitems[1]).not.toHaveFocus(); + + fireEvent.keyDown(menuitems[0], { key: 'ArrowDown', altKey: true }); + expect(menuitems[0]).toHaveFocus(); + expect(menuitems[1]).not.toHaveFocus(); + + fireEvent.keyDown(menuitems[0], { key: 'ArrowDown', metaKey: true }); + expect(menuitems[0]).toHaveFocus(); + expect(menuitems[1]).not.toHaveFocus(); + }); + + it('should call the onKeyDown and not prevent default on the event', () => { + const onKeyDown = spy(); + const { getAllByRole } = render( + + Menu Item 1 + Menu Item 2 + Menu Item 3 + , + ); + + const menuitems = getAllByRole('menuitem'); + fireEvent.keyDown(menuitems[0], { key: 'ArrowDown', ctrlKey: true }); + + expect(onKeyDown.callCount).to.equal(1); + expect(onKeyDown.firstCall.args[0]).to.have.property('ctrlKey', true); + expect(onKeyDown.firstCall.args[0]).to.have.property('defaultPrevented', false); + }); + }); }); describe('keyboard controls and tabIndex manipulation - preselected item', () => {