Skip to content

Commit b82d0da

Browse files
authored
fix: S2 menu press scaling (#7492)
* fix: S2 menu press scaling * Fix bug in useGlobalListeners
1 parent f93cb20 commit b82d0da

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

packages/@react-aria/utils/src/useGlobalListeners.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function useGlobalListeners(): GlobalListeners {
2929
listener(...args);
3030
} : listener;
3131
globalListeners.current.set(listener, {type, eventTarget, fn, options});
32-
eventTarget.addEventListener(type, listener, options);
32+
eventTarget.addEventListener(type, fn, options);
3333
}, []);
3434
let removeGlobalListener = useCallback((eventTarget, type, listener, options) => {
3535
let fn = globalListeners.current.get(listener)?.fn || listener;

packages/@react-spectrum/s2/src/Menu.tsx

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ import {centerBaseline} from './CenterBaseline';
3232
import {centerPadding, getAllowedOverrides, StyleProps} from './style-utils' with {type: 'macro'};
3333
import CheckmarkIcon from '../ui-icons/Checkmark';
3434
import ChevronRightIcon from '../ui-icons/Chevron';
35-
import {createContext, forwardRef, JSX, ReactNode, useContext, useRef} from 'react';
35+
import {createContext, forwardRef, JSX, ReactNode, useContext, useRef, useState} from 'react';
3636
import {divider} from './Divider';
37-
import {DOMRef, DOMRefValue} from '@react-types/shared';
37+
import {DOMRef, DOMRefValue, PressEvent} from '@react-types/shared';
3838
import {forwardRefType} from './types';
3939
import {HeaderContext, HeadingContext, KeyboardContext, Text, TextContext} from './Content';
4040
import {IconContext} from './Icon'; // chevron right removed??
@@ -45,6 +45,7 @@ import {Placement, useLocale} from 'react-aria';
4545
import {PopoverBase} from './Popover';
4646
import {PressResponder} from '@react-aria/interactions';
4747
import {pressScale} from './pressScale';
48+
import {useGlobalListeners} from '@react-aria/utils';
4849
import {useSpectrumContextProps} from './useSpectrumContextProps';
4950
// viewbox on LinkOut is super weird just because i copied the icon from designs...
5051
// need to strip id's from icons
@@ -520,6 +521,23 @@ export function MenuItem(props: MenuItemProps) {
520521
* linking the Menu's open state with the trigger's press state.
521522
*/
522523
function MenuTrigger(props: MenuTriggerProps) {
524+
// RAC sets isPressed via PressResponder when the menu is open.
525+
// We don't want press scaling to appear to get "stuck", so override this.
526+
// For mouse interactions, menus open on press start. When the popover underlay appears
527+
// it covers the trigger button, causing onPressEnd to fire immediately and no press scaling
528+
// to occur. We override this by listening for pointerup on the document ourselves.
529+
let [isPressed, setPressed] = useState(false);
530+
let {addGlobalListener} = useGlobalListeners();
531+
let onPressStart = (e: PressEvent) => {
532+
if (e.pointerType !== 'mouse') {
533+
return;
534+
}
535+
setPressed(true);
536+
addGlobalListener(document, 'pointerup', () => {
537+
setPressed(false);
538+
}, {once: true, capture: true});
539+
};
540+
523541
return (
524542
<InternalMenuTriggerContext.Provider
525543
value={{
@@ -528,9 +546,7 @@ function MenuTrigger(props: MenuTriggerProps) {
528546
shouldFlip: props.shouldFlip
529547
}}>
530548
<AriaMenuTrigger {...props}>
531-
{/* RAC sets isPressed via PressResponder when the menu is open.
532-
We don't want press scaling to appear to get "stuck", so override this. */}
533-
<PressResponder isPressed={false}>
549+
<PressResponder onPressStart={onPressStart} isPressed={isPressed}>
534550
{props.children}
535551
</PressResponder>
536552
</AriaMenuTrigger>

0 commit comments

Comments
 (0)