diff --git a/packages/react-native-web/src/exports/Pressable/__tests__/__snapshots__/index-test.js.snap b/packages/react-native-web/src/exports/Pressable/__tests__/__snapshots__/index-test.js.snap
index 1ba73854..52e058a9 100644
--- a/packages/react-native-web/src/exports/Pressable/__tests__/__snapshots__/index-test.js.snap
+++ b/packages/react-native-web/src/exports/Pressable/__tests__/__snapshots__/index-test.js.snap
@@ -61,14 +61,14 @@ exports[`components/Pressable hover interaction 3`] = `
/>
`;
-exports[`components/Pressable press interaction (keyboard) 1`] = `
+exports[`components/Pressable press interaction (keyboard) trigger press when keyup is on the same element 1`] = `
`;
-exports[`components/Pressable press interaction (keyboard) 2`] = `
+exports[`components/Pressable press interaction (keyboard) trigger press when keyup is on the same element 2`] = `
`;
-exports[`components/Pressable press interaction (keyboard) 3`] = `null`;
+exports[`components/Pressable press interaction (keyboard) trigger press when keyup is on the same element 3`] = `null`;
exports[`components/Pressable press interaction (pointer) 1`] = `
{
expect(onContextMenu).toBeCalled();
});
- test('press interaction (keyboard)', () => {
- let container;
- const onPress = jest.fn();
- const onPressIn = jest.fn();
- const onPressOut = jest.fn();
- const ref = React.createRef();
+ describe('press interaction (keyboard)', () => {
+ test('trigger press when keyup is on the same element', () => {
+ let container;
+ const onPress = jest.fn();
+ const onPressIn = jest.fn();
+ const onPressOut = jest.fn();
+ const ref = React.createRef();
- function TestCase() {
- const [shown, setShown] = React.useState(true);
- return shown ? (
-
- pressed ? : null
- }
- onPress={(e) => {
- onPress(e);
- setShown(false);
- }}
- onPressIn={onPressIn}
- onPressOut={onPressOut}
- ref={ref}
- style={({ pressed }) => [pressed && { outline: 'press-ring' }]}
- />
- ) : null;
- }
+ function TestCase() {
+ const [shown, setShown] = React.useState(true);
+ return shown ? (
+
+ pressed ? : null
+ }
+ onPress={(e) => {
+ onPress(e);
+ setShown(false);
+ }}
+ onPressIn={onPressIn}
+ onPressOut={onPressOut}
+ ref={ref}
+ style={({ pressed }) => [pressed && { outline: 'press-ring' }]}
+ />
+ ) : null;
+ }
- act(() => {
- ({ container } = render());
+ act(() => {
+ ({ container } = render());
+ });
+ const target = createEventTarget(ref.current);
+ expect(container.firstChild).toMatchSnapshot();
+ act(() => {
+ target.keydown({ key: 'Enter' });
+ jest.runAllTimers();
+ });
+ expect(onPressIn).toBeCalled();
+ expect(container.firstChild).toMatchSnapshot();
+ act(() => {
+ target.keyup({ key: 'Enter' });
+ jest.runAllTimers();
+ });
+ expect(onPressOut).toBeCalled();
+ expect(onPress).toBeCalled();
+ expect(container.firstChild).toMatchSnapshot();
});
- const target = createEventTarget(ref.current);
- expect(container.firstChild).toMatchSnapshot();
- act(() => {
- target.keydown({ key: 'Enter' });
- jest.runAllTimers();
+
+ test('ignore press when keyup is on a different element', () => {
+ const onPress = jest.fn();
+ const firstRef = React.createRef();
+
+ function TestCase() {
+ return (
+ {
+ onPress(e);
+ }}
+ ref={firstRef}
+ />
+ );
+ }
+
+ act(() => {
+ render();
+ });
+ const target = createEventTarget(firstRef.current);
+ const body = createEventTarget(document.body);
+ act(() => {
+ target.keydown({ key: 'Enter' });
+ body.keyup({ key: 'Enter' });
+ jest.runAllTimers();
+ });
+ expect(onPress).not.toBeCalled();
});
- expect(onPressIn).toBeCalled();
- expect(container.firstChild).toMatchSnapshot();
- act(() => {
- target.keyup({ key: 'Enter' });
- jest.runAllTimers();
- });
- expect(onPressOut).toBeCalled();
- expect(onPress).toBeCalled();
- expect(container.firstChild).toMatchSnapshot();
});
test('press interaction as button (keyboard)', () => {
diff --git a/packages/react-native-web/src/modules/usePressEvents/PressResponder.js b/packages/react-native-web/src/modules/usePressEvents/PressResponder.js
index 857db94b..fa9d26d7 100644
--- a/packages/react-native-web/src/modules/usePressEvents/PressResponder.js
+++ b/packages/react-native-web/src/modules/usePressEvents/PressResponder.js
@@ -233,6 +233,7 @@ export default class PressResponder {
pageY: number
|}>;
_touchState: TouchState = NOT_RESPONDER;
+ _responderElement: ?HTMLElement = null;
constructor(config: PressResponderConfig) {
this.configure(config);
@@ -320,10 +321,13 @@ export default class PressResponder {
elementType === 'input' ||
elementType === 'select' ||
elementType === 'textarea';
+ const isActiveElement = this._responderElement === target;
- if (onPress != null && !isNativeInteractiveElement) {
+ if (onPress != null && !isNativeInteractiveElement && isActiveElement) {
onPress(event);
}
+
+ this._responderElement = null;
}
};
@@ -345,6 +349,7 @@ export default class PressResponder {
if (!disabled && isValidKeyPress(event)) {
if (this._touchState === NOT_RESPONDER) {
start(event, false);
+ this._responderElement = target;
// Listen to 'keyup' on document to account for situations where
// focus is moved to another element during 'keydown'.
document.addEventListener('keyup', keyupHandler);