diff --git a/web/components/menu.react.js b/web/components/menu.react.js --- a/web/components/menu.react.js +++ b/web/components/menu.react.js @@ -3,6 +3,7 @@ import classnames from 'classnames'; import * as React from 'react'; +import { useRenderMenu } from '../menu-provider.react'; import css from './menu.css'; type MenuVariant = 'thread-actions' | 'member-actions'; @@ -11,12 +12,24 @@ +icon: React.Node, +children: $ReadOnlyArray, +variant?: MenuVariant, + +onChange?: boolean => void, }; function Menu(props: MenuProps): React.Node { const [isOpen, setIsOpen] = React.useState(false); + const [buttonPosition, setButtonPosition] = React.useState(null); - const { icon, children, variant = 'thread-actions' } = props; + const buttonRef = React.useRef(); + const renderMenu = useRenderMenu(); + const { icon, children, variant = 'thread-actions', onChange } = props; + + const updatePosition = React.useCallback(() => { + if (buttonRef.current) { + setButtonPosition(buttonRef.current.getBoundingClientRect()); + } + }, []); + + React.useEffect(updatePosition, [updatePosition]); const closeMenuCallback = React.useCallback(() => { document.removeEventListener('click', closeMenuCallback); @@ -25,6 +38,20 @@ } }, [isOpen]); + React.useEffect(() => { + if (onChange) { + onChange(isOpen); + } + }, [isOpen, onChange]); + + React.useEffect(() => { + if (!window) { + return undefined; + } + + window.addEventListener('resize', updatePosition); + return () => window.removeEventListener('resize', updatePosition); + }); React.useEffect(() => { if (!document || !isOpen) { return undefined; @@ -34,8 +61,9 @@ }, [closeMenuCallback, isOpen]); const switchMenuCallback = React.useCallback(() => { + updatePosition(); setIsOpen(isMenuOpen => !isMenuOpen); - }, []); + }, [updatePosition]); if (children.length === 0) { return null; @@ -48,20 +76,30 @@ [css.menuActionListMemberActions]: variant === 'member-actions', }); - menuActionList = ( -
+ const actionListStyle = buttonPosition + ? { + top: buttonPosition.top, + left: buttonPosition.left, + } + : {}; + menuActionList = renderMenu( +
{children}
-
+
, ); } return ( -
- {menuActionList} -
+ ); }