Skip to content

Commit 77fa19d

Browse files
authored
Ensure 2 renders for submenu portal container (#5828)
1 parent 7122c20 commit 77fa19d

File tree

5 files changed

+19
-17
lines changed

5 files changed

+19
-17
lines changed

packages/@react-spectrum/menu/src/ContextualHelpTrigger.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ function ContextualHelpTrigger(props: InternalMenuDialogTriggerProps): ReactElem
4343

4444
let triggerRef = useRef<HTMLLIElement>(null);
4545
let popoverRef = useRef(null);
46-
let {popoverContainerRef, trayContainerRef, rootMenuTriggerState, menu: parentMenuRef, state} = useMenuStateContext();
46+
let {popoverContainer, trayContainerRef, rootMenuTriggerState, menu: parentMenuRef, state} = useMenuStateContext();
4747
let triggerNode = state.collection.getItem(targetKey);
4848
let submenuTriggerState = UNSTABLE_useSubmenuTriggerState({triggerKey: targetKey}, {...rootMenuTriggerState, ...state});
4949
let submenuRef = unwrapDOMRef(popoverRef);
@@ -145,7 +145,7 @@ function ContextualHelpTrigger(props: InternalMenuDialogTriggerProps): ReactElem
145145
UNSAFE_className={classNames(styles, 'spectrum-Submenu-popover')}
146146
onDismissButtonPress={onDismissButtonPress}
147147
onBlurWithin={onBlurWithin}
148-
container={popoverContainerRef.current}
148+
container={popoverContainer}
149149
state={submenuTriggerState}
150150
ref={popoverRef}
151151
triggerRef={triggerRef}

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,26 +40,28 @@ function Menu<T extends object>(props: SpectrumMenuProps<T>, ref: DOMRef<HTMLDiv
4040
...mergeProps(contextProps, props)
4141
};
4242
let domRef = useDOMRef(ref);
43-
let popoverContainerRef = useRef(null);
43+
let [popoverContainer, setPopoverContainer] = useState(null);
4444
let trayContainerRef = useRef(null);
4545
let state = useTreeState(completeProps);
4646
let submenuRef = useRef<HTMLDivElement>(null);
4747
let {menuProps} = useMenu(completeProps, state, domRef);
4848
let {styleProps} = useStyleProps(completeProps);
4949
useSyncRef(contextProps, domRef);
5050
let [leftOffset, setLeftOffset] = useState({left: 0});
51+
let prevPopoverContainer = useRef(null);
5152
useEffect(() => {
52-
if (popoverContainerRef.current) {
53-
let {left} = popoverContainerRef.current.getBoundingClientRect();
53+
if (popoverContainer && prevPopoverContainer.current !== popoverContainer && leftOffset.left === 0) {
54+
prevPopoverContainer.current = popoverContainer;
55+
let {left} = popoverContainer.getBoundingClientRect();
5456
setLeftOffset({left: -1 * left});
5557
}
56-
}, []);
58+
}, [leftOffset, popoverContainer]);
5759

5860
let menuLevel = contextProps.submenuLevel ?? -1;
5961
let hasOpenSubmenu = state.collection.getItem(rootMenuTriggerState?.UNSTABLE_expandedKeysStack[menuLevel + 1]) != null;
6062
// TODO: add slide transition
6163
return (
62-
<MenuStateContext.Provider value={{popoverContainerRef, trayContainerRef, menu: domRef, submenu: submenuRef, rootMenuTriggerState, state}}>
64+
<MenuStateContext.Provider value={{popoverContainer, trayContainerRef, menu: domRef, submenu: submenuRef, rootMenuTriggerState, state}}>
6365
<div style={{height: hasOpenSubmenu ? '100%' : undefined}} ref={trayContainerRef} />
6466
<FocusScope>
6567
<TrayHeaderWrapper
@@ -106,7 +108,7 @@ function Menu<T extends object>(props: SpectrumMenuProps<T>, ref: DOMRef<HTMLDiv
106108
})}
107109
</div>
108110
</TrayHeaderWrapper>
109-
{rootMenuTriggerState?.isOpen && <div ref={popoverContainerRef} style={{width: '100vw', position: 'absolute', top: -5, ...leftOffset}} /> }
111+
{rootMenuTriggerState?.isOpen && <div ref={setPopoverContainer} style={{width: '100vw', position: 'absolute', top: -5, ...leftOffset}} /> }
110112
</FocusScope>
111113
</MenuStateContext.Provider>
112114
);

packages/@react-spectrum/menu/src/SubmenuTrigger.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {useLocale} from '@react-aria/i18n';
2424

2525
interface SubmenuTriggerProps {
2626
/**
27-
* The contents of the SubmenuTrigger - a Item and a Menu.
27+
* The contents of the SubmenuTrigger - an Item and a Menu.
2828
*/
2929
children: ReactElement[],
3030
targetKey: Key
@@ -40,7 +40,7 @@ function SubmenuTrigger(props: SubmenuTriggerProps) {
4040
} = props;
4141

4242
let [menuTrigger, menu] = React.Children.toArray(children);
43-
let {popoverContainerRef, trayContainerRef, menu: parentMenuRef, submenu: menuRef, rootMenuTriggerState, state} = useMenuStateContext();
43+
let {popoverContainer, trayContainerRef, menu: parentMenuRef, submenu: menuRef, rootMenuTriggerState, state} = useMenuStateContext();
4444
let triggerNode = state.collection.getItem(targetKey);
4545
let submenuTriggerState = UNSTABLE_useSubmenuTriggerState({triggerKey: targetKey}, rootMenuTriggerState);
4646
let {submenuTriggerProps, submenuProps, popoverProps} = UNSTABLE_useSubmenuTrigger({
@@ -101,7 +101,7 @@ function SubmenuTrigger(props: SubmenuTriggerProps) {
101101
{...popoverProps}
102102
onDismissButtonPress={onDismissButtonPress}
103103
UNSAFE_className={classNames(styles, 'spectrum-Submenu-popover')}
104-
container={popoverContainerRef.current}
104+
container={popoverContainer}
105105
containerPadding={0}
106106
crossOffset={offset}
107107
offset={offset}

packages/@react-spectrum/menu/src/context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export function useSubmenuTriggerContext(): SubmenuTriggerContextValue {
4949

5050
export interface MenuStateContextValue<T> {
5151
state?: TreeState<T>,
52-
popoverContainerRef?: RefObject<HTMLElement>,
52+
popoverContainer?: HTMLElement,
5353
trayContainerRef?: RefObject<HTMLElement>,
5454
menu?: RefObject<HTMLDivElement>,
5555
submenu?: RefObject<HTMLDivElement>,

packages/react-aria-components/src/Menu.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {UNSTABLE_useSubmenuTrigger} from '@react-aria/menu';
3131
export const MenuContext = createContext<ContextValue<MenuProps<any>, HTMLDivElement>>(null);
3232
export const MenuStateContext = createContext<TreeState<unknown> | null>(null);
3333
export const RootMenuTriggerStateContext = createContext<RootMenuTriggerState | null>(null);
34-
export const SubmenuContext = createContext<{popoverContainerRef: RefObject<Element>} | null>(null);
34+
export const SubmenuContext = createContext<{popoverContainer: Element | null} | null>(null);
3535

3636
export interface MenuTriggerProps extends BaseMenuTriggerProps {
3737
children?: ReactNode
@@ -146,7 +146,7 @@ function MenuInner<T extends object>({props, collection, menuRef: ref}: MenuInne
146146
collection,
147147
children: undefined
148148
});
149-
let popoverContainerRef = useRef<HTMLDivElement>(null);
149+
let [popoverContainer, setPopoverContainer] = useState<HTMLDivElement | null>(null);
150150
let {menuProps} = useMenu(props, state, ref);
151151

152152
let children = useCachedChildren({
@@ -181,12 +181,12 @@ function MenuInner<T extends object>({props, collection, menuRef: ref}: MenuInne
181181
values={[
182182
[MenuStateContext, state],
183183
[SeparatorContext, {elementType: 'div'}],
184-
[SubmenuContext, {popoverContainerRef}]
184+
[SubmenuContext, {popoverContainer}]
185185
]}>
186186
{children}
187187
</Provider>
188188
</div>
189-
<div ref={popoverContainerRef} style={{width: '100vw', position: 'absolute', top: 0}} />
189+
<div ref={setPopoverContainer} style={{width: '100vw', position: 'absolute', top: 0}} />
190190
</FocusScope>
191191
);
192192
}
@@ -398,7 +398,7 @@ function MenuItemTriggerInner<T>({item, popover, parentMenuRef, delay}: MenuItem
398398
trigger: 'SubmenuTrigger',
399399
triggerRef: ref,
400400
placement: 'end top',
401-
UNSTABLE_portalContainer: submenuContext.popoverContainerRef.current || undefined,
401+
UNSTABLE_portalContainer: submenuContext.popoverContainer || undefined,
402402
...popoverProps
403403
}]
404404
]}>

0 commit comments

Comments
 (0)