diff --git a/packages/react-interactions/events/src/dom/PressLegacy.js b/packages/react-interactions/events/src/dom/PressLegacy.js
index 19ba8adda01af..d2c8c3d031b79 100644
--- a/packages/react-interactions/events/src/dom/PressLegacy.js
+++ b/packages/react-interactions/events/src/dom/PressLegacy.js
@@ -126,6 +126,7 @@ const rootEventTypes = hasPointerEvents
'click',
'keyup',
'scroll',
+ 'blur',
]
: [
'click',
@@ -138,6 +139,7 @@ const rootEventTypes = hasPointerEvents
'dragstart',
'mouseup_active',
'touchend',
+ 'blur',
];
function isFunction(obj): boolean {
@@ -881,6 +883,21 @@ const pressResponderImpl = {
case 'touchcancel':
case 'dragstart': {
dispatchCancel(event, context, props, state);
+ break;
+ }
+ case 'blur': {
+ // If we encounter a blur event that moves focus to
+ // the window, then the relatedTarget will be null.
+ // In this case, we should cancel the active press.
+ // Alternatively, if the blur target matches the
+ // current pressed target, we should also cancel
+ // the active press.
+ if (
+ isPressed &&
+ (nativeEvent.relatedTarget === null || target === state.pressTarget)
+ ) {
+ dispatchCancel(event, context, props, state);
+ }
}
}
},
diff --git a/packages/react-interactions/events/src/dom/__tests__/PressLegacy-test.internal.js b/packages/react-interactions/events/src/dom/__tests__/PressLegacy-test.internal.js
index 52969f0e68cff..65cb1141f8b11 100644
--- a/packages/react-interactions/events/src/dom/__tests__/PressLegacy-test.internal.js
+++ b/packages/react-interactions/events/src/dom/__tests__/PressLegacy-test.internal.js
@@ -1167,4 +1167,27 @@ describe.each(environmentTable)('Press responder', hasPointerEvents => {
expect(onPressStart).toBeCalled();
expect(onPressEnd).toBeCalled();
});
+
+ it('focus moving to the window should stop the press', () => {
+ const onPress = jest.fn(e => e.preventDefault());
+ const onPressStart = jest.fn(e => e.preventDefault());
+ const onPressEnd = jest.fn(e => e.preventDefault());
+ const buttonRef = React.createRef();
+
+ const Component = () => {
+ const listener = usePress({onPress, onPressStart, onPressEnd});
+ return ;
+ };
+ ReactDOM.render(, container);
+
+ const target = createEventTarget(buttonRef.current);
+ target.pointerdown();
+ const secondTarget = createEventTarget(document);
+ // relatedTarget is null when moving focus to window
+ expect(onPressStart).toBeCalled();
+ secondTarget.blur({relatedTarget: null});
+ expect(onPressEnd).toBeCalled();
+ target.pointerup();
+ expect(onPress).not.toBeCalled();
+ });
});