Skip to content

Commit 63fe08e

Browse files
AndaristNicolas Gallagher
authored andcommitted
React Events: allow Tab+Alt on Mac in Focus responder (#15679)
* Fix issue with Tab+alt not being considered as isGlobalFocusVisible candidate on Mac * Add test for Tab+alt on Mac setting pointerType: "keyboard" on a focus event
1 parent 113497c commit 63fe08e

2 files changed

Lines changed: 47 additions & 8 deletions

File tree

packages/react-events/src/Focus.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ type FocusEvent = {|
3939
timeStamp: number,
4040
|};
4141

42+
const isMac =
43+
typeof window !== 'undefined' && window.navigator != null
44+
? /^Mac/.test(window.navigator.platform)
45+
: false;
46+
4247
const targetEventTypes = [
4348
{name: 'focus', passive: true},
4449
{name: 'blur', passive: true},
@@ -304,7 +309,11 @@ const FocusResponder = {
304309
const nativeEvent = event.nativeEvent;
305310
if (
306311
nativeEvent.key === 'Tab' &&
307-
!(nativeEvent.metaKey || nativeEvent.altKey || nativeEvent.ctrlKey)
312+
!(
313+
nativeEvent.metaKey ||
314+
(!isMac && nativeEvent.altKey) ||
315+
nativeEvent.ctrlKey
316+
)
308317
) {
309318
state.pointerType = 'keyboard';
310319
isGlobalFocusVisible = true;

packages/react-events/src/__tests__/Focus-test.internal.js

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,20 @@ const createPointerEvent = (type, data) => {
3939
return event;
4040
};
4141

42+
const modulesInit = () => {
43+
ReactFeatureFlags = require('shared/ReactFeatureFlags');
44+
ReactFeatureFlags.enableEventAPI = true;
45+
React = require('react');
46+
ReactDOM = require('react-dom');
47+
Focus = require('react-events/focus');
48+
};
49+
4250
describe('Focus event responder', () => {
4351
let container;
4452

4553
beforeEach(() => {
4654
jest.resetModules();
47-
ReactFeatureFlags = require('shared/ReactFeatureFlags');
48-
ReactFeatureFlags.enableEventAPI = true;
49-
React = require('react');
50-
ReactDOM = require('react-dom');
51-
Focus = require('react-events/focus');
55+
modulesInit();
5256

5357
container = document.createElement('div');
5458
document.body.appendChild(container);
@@ -107,7 +111,7 @@ describe('Focus event responder', () => {
107111
describe('onFocus', () => {
108112
let onFocus, ref, innerRef;
109113

110-
beforeEach(() => {
114+
const componentInit = () => {
111115
onFocus = jest.fn();
112116
ref = React.createRef();
113117
innerRef = React.createRef();
@@ -119,7 +123,9 @@ describe('Focus event responder', () => {
119123
</Focus>
120124
);
121125
ReactDOM.render(element, container);
122-
});
126+
};
127+
128+
beforeEach(componentInit);
123129

124130
it('is called after "focus" event', () => {
125131
ref.current.dispatchEvent(createFocusEvent('focus'));
@@ -204,6 +210,30 @@ describe('Focus event responder', () => {
204210
expect.objectContaining({pointerType: 'keyboard'}),
205211
);
206212
});
213+
214+
it('is called with the correct pointerType using Tab+altKey on Mac', () => {
215+
jest.resetModules();
216+
const platformGetter = jest.spyOn(global.navigator, 'platform', 'get');
217+
platformGetter.mockReturnValue('MacIntel');
218+
modulesInit();
219+
componentInit();
220+
221+
ref.current.dispatchEvent(
222+
createPointerEvent('keypress', {
223+
key: 'Tab',
224+
altKey: true,
225+
}),
226+
);
227+
ref.current.dispatchEvent(createFocusEvent('focus'));
228+
expect(onFocus).toHaveBeenCalledTimes(1);
229+
expect(onFocus).toHaveBeenCalledWith(
230+
expect.objectContaining({
231+
pointerType: 'keyboard',
232+
}),
233+
);
234+
235+
platformGetter.mockClear();
236+
});
207237
});
208238

209239
describe('onFocusChange', () => {

0 commit comments

Comments
 (0)