Skip to content

Commit fcb4579

Browse files
committed
refactor(useMenu): restore previous behavior on TAB keydown
1 parent b586c41 commit fcb4579

File tree

2 files changed

+15
-22
lines changed

2 files changed

+15
-22
lines changed

packages/menu/src/MenuContainer.spec.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,7 @@ describe('MenuContainer', () => {
916916
expect(fruit1).toHaveAttribute('aria-checked', 'true');
917917
});
918918

919-
it('returns normal keyboard navigation after menu closes', async () => {
919+
it('returns focus to trigger before resuming normal tab navigation after menu closes', async () => {
920920
const { getByText, getByTestId } = render(
921921
<>
922922
<TestMenu items={ITEMS} />
@@ -940,6 +940,12 @@ describe('MenuContainer', () => {
940940
});
941941

942942
expect(menu).not.toBeVisible();
943+
expect(trigger).toHaveFocus();
944+
945+
await waitFor(async () => {
946+
await user.keyboard('{Tab}');
947+
});
948+
943949
expect(nextFocusedElement).toHaveFocus();
944950
});
945951

packages/menu/src/useMenu.ts

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import React, {
1212
useEffect,
1313
useMemo,
1414
useReducer,
15-
useRef,
1615
useState
1716
} from 'react';
1817
import { useSelection } from '@zendeskgarden/container-selection';
@@ -89,7 +88,6 @@ export const useMenu = <T extends HTMLElement = HTMLElement, M extends HTMLEleme
8988
}, {}),
9089
[values]
9190
);
92-
const isTabNavigationRef = useRef(false);
9391

9492
/**
9593
* State
@@ -317,9 +315,7 @@ export const useMenu = <T extends HTMLElement = HTMLElement, M extends HTMLEleme
317315
let changeType;
318316
let nextFocusedValue;
319317

320-
if (key === KEYS.TAB) {
321-
isTabNavigationRef.current = true;
322-
} else if (isArrowKey) {
318+
if (isArrowKey) {
323319
changeType = StateChangeTypes[`TriggerKeyDown${key}`];
324320
nextFocusedValue = KEYS.UP === key ? values[values.length - 1] : values[0];
325321
} else if (isSelectKey) {
@@ -364,19 +360,15 @@ export const useMenu = <T extends HTMLElement = HTMLElement, M extends HTMLEleme
364360
(event: KeyboardEvent) => {
365361
const { key } = event;
366362

367-
if (key === KEYS.ESCAPE) {
363+
if ([KEYS.ESCAPE, KEYS.TAB].includes(key)) {
368364
event.preventDefault();
369365
event.stopPropagation();
370366

371-
const type = StateChangeTypes.MenuKeyDownEscape;
367+
const type = StateChangeTypes[key === KEYS.ESCAPE ? 'MenuKeyDownEscape' : 'MenuKeyDownTab'];
368+
369+
// TODO: Investigate why focus goes to body instead of next interactive element on TAB keydown. Meanwhile, returning focus to trigger.
372370
returnFocusToTrigger();
373-
closeMenu(type);
374-
} else if (key === KEYS.TAB) {
375-
// Let the natural tab order continue.
376-
// Close the menu without returning focus to trigger.
377-
isTabNavigationRef.current = true;
378371

379-
const type = StateChangeTypes.MenuKeyDownTab;
380372
closeMenu(type);
381373
}
382374
},
@@ -401,9 +393,8 @@ export const useMenu = <T extends HTMLElement = HTMLElement, M extends HTMLEleme
401393
* @see https://github.com/jestjs/jest/blob/v29.7.0/packages/jest-environment-jsdom/package.json
402394
*
403395
* 3. Skip focus-return to trigger in these scenarios:
404-
* a. User is navigating via Tab key
405-
* b. Focus is moving to another focusable element
406-
* c. Menu is closed and focus would naturally go to body
396+
* a. Focus is moving to another focusable element
397+
* b. Menu is closed and focus would naturally go to body
407398
*/
408399
const handleBlur = useCallback(
409400
(event: React.FocusEvent) => {
@@ -421,14 +412,10 @@ export const useMenu = <T extends HTMLElement = HTMLElement, M extends HTMLEleme
421412
event.relatedTarget?.nodeName !== '#document'; /* [2] */
422413

423414
const shouldSkipFocusReturn =
424-
isTabNavigationRef.current ||
425-
nextElementIsFocusable ||
426-
(!controlledIsExpanded && !nextElementIsFocusable); /* [3] */
415+
nextElementIsFocusable || (!controlledIsExpanded && !nextElementIsFocusable); /* [3] */
427416

428417
returnFocusToTrigger(shouldSkipFocusReturn);
429418

430-
isTabNavigationRef.current = false;
431-
432419
closeMenu(StateChangeTypes.MenuBlur);
433420
}
434421
});

0 commit comments

Comments
 (0)