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
Mateusz Burzyński committed
May 31, 2019 at 23:33 UTC
63fe08eef56f92956c2d785701cad7f743501e35
2 files changed
+47
-8
packages/react-events/src/Focus.js
+10
-1
@@ -39,6 +39,11 @@ type FocusEvent = {|
39
timeStamp: number,
40
|};
41
42
+const isMac =
43
+ typeof window !== 'undefined' && window.navigator != null
44
+ ? /^Mac/.test(window.navigator.platform)
45
+ : false;
46
+
47
const targetEventTypes = [
48
{name: 'focus', passive: true},
49
{name: 'blur', passive: true},
@@ -304,7 +309,11 @@ const FocusResponder = {
309
const nativeEvent = event.nativeEvent;
310
if (
311
nativeEvent.key === 'Tab' &&
307
- !(nativeEvent.metaKey || nativeEvent.altKey || nativeEvent.ctrlKey)
312
+ !(
313
+ nativeEvent.metaKey ||
314
+ (!isMac && nativeEvent.altKey) ||
315
+ nativeEvent.ctrlKey
316
+ )
317
) {
318
state.pointerType = 'keyboard';
319
isGlobalFocusVisible = true;
packages/react-events/src/__tests__/Focus-test.internal.js
+37
-7
@@ -39,16 +39,20 @@ const createPointerEvent = (type, data) => {
39
return event;
40
};
41
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
+
50
describe('Focus event responder', () => {
51
let container;
52
53
beforeEach(() => {
54
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();
56
57
container = document.createElement('div');
58
document.body.appendChild(container);
@@ -107,7 +111,7 @@ describe('Focus event responder', () => {
111
describe('onFocus', () => {
112
let onFocus, ref, innerRef;
113
110
- beforeEach(() => {
114
+ const componentInit = () => {
115
onFocus = jest.fn();
116
ref = React.createRef();
117
innerRef = React.createRef();
@@ -119,7 +123,9 @@ describe('Focus event responder', () => {
123
</Focus>
124
);
125
ReactDOM.render(element, container);
122
- });
126
+ };
127
+
128
+ beforeEach(componentInit);
129
130
it('is called after "focus" event', () => {
131
ref.current.dispatchEvent(createFocusEvent('focus'));
@@ -204,6 +210,30 @@ describe('Focus event responder', () => {
210
expect.objectContaining({pointerType: 'keyboard'}),
211
);
212
});
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
+ });
237
});
238
239
describe('onFocusChange', () => {