diff --git a/packages/menu/src/MenuContainer.spec.tsx b/packages/menu/src/MenuContainer.spec.tsx index 93ea755f4..0acea5a2c 100644 --- a/packages/menu/src/MenuContainer.spec.tsx +++ b/packages/menu/src/MenuContainer.spec.tsx @@ -371,6 +371,20 @@ describe('MenuContainer', () => { expect(trigger).toHaveFocus(); }); + + it('does not return focus to trigger when Escape key pressed in expanded menu if `restoreFocus` is false', async () => { + const { getByTestId } = render(); + const trigger = getByTestId('trigger'); + + trigger.focus(); + + await waitFor(async () => { + await user.keyboard('{ArrowDown}'); + await user.keyboard('{Escape}'); + }); + + expect(trigger).not.toHaveFocus(); + }); }); describe('menu items', () => { diff --git a/packages/menu/src/MenuContainer.tsx b/packages/menu/src/MenuContainer.tsx index e002548e7..600876d14 100644 --- a/packages/menu/src/MenuContainer.tsx +++ b/packages/menu/src/MenuContainer.tsx @@ -29,5 +29,12 @@ MenuContainer.propTypes = { defaultExpanded: PropTypes.bool, selectedItems: PropTypes.arrayOf(PropTypes.any), focusedValue: PropTypes.oneOfType([PropTypes.string]), - defaultFocusedValue: PropTypes.oneOfType([PropTypes.string]) + defaultFocusedValue: PropTypes.oneOfType([PropTypes.string]), + restoreFocus: PropTypes.bool +}; + +MenuContainer.defaultProps = { + defaultExpanded: false, + restoreFocus: true, + rtl: false }; diff --git a/packages/menu/src/types.ts b/packages/menu/src/types.ts index 201de2e1d..7e70a6570 100644 --- a/packages/menu/src/types.ts +++ b/packages/menu/src/types.ts @@ -66,6 +66,8 @@ export interface IUseMenuProps { focusedValue?: string | null; /** Determines focused value on menu initialization */ defaultFocusedValue?: string; + /** Returns focus to the trigger when the menu is collapsed */ + restoreFocus?: boolean; /** Sets the selected values in a controlled menu */ selectedItems?: ISelectedItem[]; /** diff --git a/packages/menu/src/useMenu.ts b/packages/menu/src/useMenu.ts index 06e755ac2..0ec4fa334 100644 --- a/packages/menu/src/useMenu.ts +++ b/packages/menu/src/useMenu.ts @@ -12,7 +12,6 @@ import React, { useEffect, useMemo, useReducer, - useRef, useState } from 'react'; import { useSelection } from '@zendeskgarden/container-selection'; @@ -49,6 +48,7 @@ export const useMenu = undefined, isExpanded, defaultExpanded = false, + restoreFocus = true, selectedItems, focusedValue, defaultFocusedValue @@ -94,8 +94,6 @@ export const useMenu = (false); - const focusTriggerRef = useRef(false); - const [state, dispatch] = useReducer(stateReducer, { focusedValue, isExpanded: isExpanded || defaultExpanded, @@ -135,6 +133,15 @@ export const useMenu = { + if (!skip && restoreFocus && triggerRef.current) { + triggerRef.current.focus(); + } + }, + [triggerRef, restoreFocus] + ); + const closeMenu = useCallback( (changeType: string) => { dispatch({ @@ -281,13 +288,22 @@ export const useMenu = { @@ -395,6 +420,8 @@ export const useMenu = { if (state.focusOnOpen && menuVisible && controlledFocusedValue && controlledIsExpanded) { @@ -614,13 +632,7 @@ export const useMenu =