diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d8c6e3156..20bd3a0d5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] +### Fixes +- Do not propagate keyboard events outside `Popup`'s content only when focus trap is used @sophieH29 ([#1028](https://github.com/stardust-ui/react/pull/1028)) + ### Features - Add `inline` prop in the `Popup` for rendering the content next to the trigger element @mnajdova ([#1017](https://github.com/stardust-ui/react/pull/1017)) diff --git a/packages/react/src/components/Popup/Popup.tsx b/packages/react/src/components/Popup/Popup.tsx index fe1b57fd10..f8f7f93a65 100644 --- a/packages/react/src/components/Popup/Popup.tsx +++ b/packages/react/src/components/Popup/Popup.tsx @@ -469,12 +469,7 @@ export default class Popup extends AutoControlledComponent { - // No need to propagate keydown events outside Popup - // allow only keyboard actions to execute - _.invoke(accessibility.keyHandlers.popup, 'onKeyDown', e) - e.stopPropagation() - }, + ...accessibility.keyHandlers.popup, className: popupPositionClasses, style: popupPlacementStyles, ...this.getContentProps(), @@ -483,6 +478,13 @@ export default class Popup extends AutoControlledComponent { + // No need to propagate keydown events outside Popup + // when focus trap behavior is used + // allow only keyboard actions to execute + _.invoke(accessibility.keyHandlers.popup, 'onKeyDown', e) + e.stopPropagation() + }, } as FocusTrapZoneProps const autoFocusProps = { diff --git a/packages/react/test/specs/components/Popup/Popup-test.tsx b/packages/react/test/specs/components/Popup/Popup-test.tsx index d953ce3fc4..b682f22acf 100644 --- a/packages/react/test/specs/components/Popup/Popup-test.tsx +++ b/packages/react/test/specs/components/Popup/Popup-test.tsx @@ -8,6 +8,9 @@ import { Alignment, } from 'src/components/Popup/positioningHelper' import Popup, { PopupEvents } from 'src/components/Popup/Popup' +import { Accessibility } from 'src/lib/accessibility/types' +import { popupFocusTrapBehavior, popupBehavior, dialogBehavior } from 'src/lib/accessibility/index' + import { domEvent, mountWithProvider } from '../../../utils' import * as keyboardKey from 'keyboard-key' import { ReactWrapper } from 'enzyme' @@ -68,12 +71,6 @@ describe('Popup', () => { expect(getPopupContent(popup).exists()).toBe(true) - // when popup open, check that stopPropagation is called when keyboard events are invoked - const stopPropagation = jest.fn() - const popupContentElement = getPopupContent(popup) - popupContentElement.simulate('keyDown', { stopPropagation }) - expect(stopPropagation).toHaveBeenCalledTimes(1) - // check popup closes on Esc popupTriggerElement.simulate('keydown', { keyCode: keyboardKeyToClose }) expect(getPopupContent(popup).exists()).toBe(false) @@ -266,4 +263,38 @@ describe('Popup', () => { expect(contentElement.classList.contains(Popup.Content.className)).toEqual(true) }) }) + + describe('keyboard event propagation', () => { + const expectPopupToHandleStopPropagation = ( + behavior: Accessibility, + shouldStopPropagation: boolean, + ) => { + const popup = mountWithProvider( + text to trigger popup } + content={} + accessibility={behavior} + />, + ) + + // open popup + const popupTriggerElement = popup.find(`#${triggerId}`) + popupTriggerElement.simulate('keydown', { keyCode: keyboardKey.Enter }) + + // when popup open, check that stopPropagation is called when keyboard events are invoked + const stopPropagation = jest.fn() + const popupContentElement = getPopupContent(popup) + popupContentElement.simulate('keyDown', { stopPropagation }) + expect(stopPropagation).toHaveBeenCalledTimes(shouldStopPropagation ? 1 : 0) + } + test('stops when focus trap behavior is used', () => { + expectPopupToHandleStopPropagation(popupFocusTrapBehavior, true) + }) + test('stops when dialog behavior is used', () => { + expectPopupToHandleStopPropagation(dialogBehavior, true) + }) + test('does not stop when default behavior is used', () => { + expectPopupToHandleStopPropagation(popupBehavior, false) + }) + }) })