Skip to content

Commit c2b0204

Browse files
committed
Enhance PopButton to allow putting the menu in a provided location
Previously, we always added the menu immediately after the triggering button. This can mess with CSS based on first/last child.
1 parent e88976c commit c2b0204

File tree

1 file changed

+27
-21
lines changed

1 file changed

+27
-21
lines changed

ui/frontend/PopButton.tsx

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
useRole,
1414
} from '@floating-ui/react';
1515
import React, { useCallback, useRef, useState } from 'react';
16+
import { createPortal } from 'react-dom';
1617

1718
import styles from './PopButton.module.css';
1819

@@ -23,9 +24,10 @@ interface NewPopProps {
2324
} & React.RefAttributes<HTMLButtonElement>
2425
>;
2526
Menu: React.ComponentType<{ close: () => void }>;
27+
menuContainer?: React.RefObject<HTMLDivElement>;
2628
}
2729

28-
const PopButton: React.FC<NewPopProps> = ({ Button, Menu }) => {
30+
const PopButton: React.FC<NewPopProps> = ({ Button, Menu, menuContainer }) => {
2931
const [isOpen, setIsOpen] = useState(false);
3032
const toggle = useCallback(() => setIsOpen((v) => !v), []);
3133
const close = useCallback(() => setIsOpen(false), []);
@@ -45,30 +47,34 @@ const PopButton: React.FC<NewPopProps> = ({ Button, Menu }) => {
4547

4648
const { getReferenceProps, getFloatingProps } = useInteractions([click, dismiss, role]);
4749

50+
const FloatingMenu = isOpen && (
51+
<FloatingFocusManager context={context}>
52+
<div
53+
ref={refs.setFloating}
54+
className={styles.container}
55+
style={{
56+
position: strategy,
57+
top: y ?? 0,
58+
left: x ?? 0,
59+
width: 'max-content',
60+
}}
61+
{...getFloatingProps()}
62+
>
63+
<FloatingArrow ref={arrowRef} context={context} height={10} width={20} fill="white" />
64+
<div className={containerClass}>
65+
<Menu close={close} />
66+
</div>
67+
</div>
68+
</FloatingFocusManager>
69+
);
70+
71+
const Portal = menuContainer?.current && createPortal(FloatingMenu, menuContainer.current);
72+
4873
return (
4974
<>
5075
<Button toggle={toggle} ref={refs.setReference} {...getReferenceProps()} />
5176

52-
{isOpen && (
53-
<FloatingFocusManager context={context}>
54-
<div
55-
ref={refs.setFloating}
56-
className={styles.container}
57-
style={{
58-
position: strategy,
59-
top: y ?? 0,
60-
left: x ?? 0,
61-
width: 'max-content',
62-
}}
63-
{...getFloatingProps()}
64-
>
65-
<FloatingArrow ref={arrowRef} context={context} height={10} width={20} fill="white" />
66-
<div className={styles.content}>
67-
<Menu close={close} />
68-
</div>
69-
</div>
70-
</FloatingFocusManager>
71-
)}
77+
{Portal || FloatingMenu}
7278
</>
7379
);
7480
};

0 commit comments

Comments
 (0)