MCPcopy Create free account
hub / github.com/adobe/react-spectrum / useMenuTrigger

Function useMenuTrigger

packages/react-aria/src/menu/useMenuTrigger.ts:53–209  ·  view source on GitHub ↗
(
  props: AriaMenuTriggerProps,
  state: MenuTriggerState,
  ref: RefObject<Element | null>
)

Source from the content-addressed store, hash-verified

51 * @param ref - Ref to the HTML element trigger for the menu.
52 */
53export function useMenuTrigger<T>(
54 props: AriaMenuTriggerProps,
55 state: MenuTriggerState,
56 ref: RefObject<Element | null>
57): MenuTriggerAria<T> {
58 let {type = 'menu', isDisabled, trigger = 'press'} = props;
59
60 let menuTriggerId = useId();
61 let {triggerProps, overlayProps} = useOverlayTrigger({type}, state, ref);
62
63 let open = (
64 shouldOpen: boolean,
65 e: KeyboardEvent,
66 focusStrategy: FocusStrategy = 'first'
67 ): boolean | void => {
68 if (!shouldOpen || e.isDefaultPrevented()) {
69 return false;
70 }
71 state.toggle(focusStrategy);
72 };
73
74 // React puts listeners on the same root, so even if propagation was stopped, immediate propagation is still possible.
75 // useTypeSelect will handle the spacebar first if it's running, so we don't want to open if it's handled it already.
76 // We use isDefaultPrevented() instead of isPropagationStopped() because createEventHandler stops propagation by default.
77 // And default prevented means that the event was handled by something else (typeahead), so we don't want to open the menu.
78 let {keyboardProps} = useKeyboard({
79 isDisabled,
80 shortcuts: {
81 Enter: e => {
82 return open(trigger !== 'longPress', e, 'first');
83 },
84 ' ': e => {
85 return open(trigger !== 'longPress', e, 'first');
86 },
87 ArrowDown: e => {
88 return open(trigger !== 'longPress', e, 'first');
89 },
90 ArrowUp: e => {
91 return open(trigger !== 'longPress', e, 'last');
92 },
93 'Alt+Enter': e => {
94 return open(trigger === 'longPress', e, 'first');
95 },
96 'Alt+ ': e => {
97 return open(trigger === 'longPress', e, 'first');
98 },
99 // Alt+Arrow* must open for both trigger modes: for `press` it matches the same `e.key` cases as
100 // plain Arrow*; for `longPress`, plain arrows are ignored elsewhere and Alt+Arrow is the opener
101 // (see legacy `if (trigger === 'longPress' && !e.altKey) return` before the ArrowDown/Up switch).
102 'Alt+ArrowDown': e => {
103 return open(true, e, 'first');
104 },
105 'Alt+ArrowUp': e => {
106 return open(true, e, 'last');
107 }
108 }
109 });
110

Callers 7

renderMenuTriggerHookFunction · 0.90
useComboBoxFunction · 0.90
useSelectFunction · 0.90
MenuButtonFunction · 0.90
MenuTriggerFunction · 0.90
MenuTrigger.tsxFile · 0.90
MenuButtonFunction · 0.90

Calls 10

useIdFunction · 0.90
useOverlayTriggerFunction · 0.90
useKeyboardFunction · 0.90
useLongPressFunction · 0.90
useContextMenuFunction · 0.90
addEventListenerMethod · 0.80
removeEventListenerMethod · 0.80
openFunction · 0.70
formatMethod · 0.45

Tested by 1

renderMenuTriggerHookFunction · 0.72