Skip to content

Commit a29a273

Browse files
authored
[react-interactions] Ensure blur to window disengages press (facebook#18125)
1 parent bf13d3e commit a29a273

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

packages/react-interactions/events/src/dom/PressLegacy.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ const rootEventTypes = hasPointerEvents
126126
'click',
127127
'keyup',
128128
'scroll',
129+
'blur',
129130
]
130131
: [
131132
'click',
@@ -138,6 +139,7 @@ const rootEventTypes = hasPointerEvents
138139
'dragstart',
139140
'mouseup_active',
140141
'touchend',
142+
'blur',
141143
];
142144

143145
function isFunction(obj): boolean {
@@ -881,6 +883,21 @@ const pressResponderImpl = {
881883
case 'touchcancel':
882884
case 'dragstart': {
883885
dispatchCancel(event, context, props, state);
886+
break;
887+
}
888+
case 'blur': {
889+
// If we encounter a blur event that moves focus to
890+
// the window, then the relatedTarget will be null.
891+
// In this case, we should cancel the active press.
892+
// Alternatively, if the blur target matches the
893+
// current pressed target, we should also cancel
894+
// the active press.
895+
if (
896+
isPressed &&
897+
(nativeEvent.relatedTarget === null || target === state.pressTarget)
898+
) {
899+
dispatchCancel(event, context, props, state);
900+
}
884901
}
885902
}
886903
},

packages/react-interactions/events/src/dom/__tests__/PressLegacy-test.internal.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,4 +1167,27 @@ describe.each(environmentTable)('Press responder', hasPointerEvents => {
11671167
expect(onPressStart).toBeCalled();
11681168
expect(onPressEnd).toBeCalled();
11691169
});
1170+
1171+
it('focus moving to the window should stop the press', () => {
1172+
const onPress = jest.fn(e => e.preventDefault());
1173+
const onPressStart = jest.fn(e => e.preventDefault());
1174+
const onPressEnd = jest.fn(e => e.preventDefault());
1175+
const buttonRef = React.createRef();
1176+
1177+
const Component = () => {
1178+
const listener = usePress({onPress, onPressStart, onPressEnd});
1179+
return <button ref={buttonRef} DEPRECATED_flareListeners={listener} />;
1180+
};
1181+
ReactDOM.render(<Component />, container);
1182+
1183+
const target = createEventTarget(buttonRef.current);
1184+
target.pointerdown();
1185+
const secondTarget = createEventTarget(document);
1186+
// relatedTarget is null when moving focus to window
1187+
expect(onPressStart).toBeCalled();
1188+
secondTarget.blur({relatedTarget: null});
1189+
expect(onPressEnd).toBeCalled();
1190+
target.pointerup();
1191+
expect(onPress).not.toBeCalled();
1192+
});
11701193
});

0 commit comments

Comments
 (0)