diff --git a/web/app.react.js b/web/app.react.js --- a/web/app.react.js +++ b/web/app.react.js @@ -28,6 +28,7 @@ import Chat from './chat/chat.react'; import InputStateContainer from './input/input-state-container.react'; import LoadingIndicator from './loading-indicator.react'; +import { MenuProvider } from './menu-provider.react'; import { ModalProvider, useModalContext } from './modals/modal-provider.react'; import DisconnectedBar from './redux/disconnected-bar'; import DisconnectedBarVisibilityHandler from './redux/disconnected-bar-visibility-handler'; @@ -129,10 +130,12 @@ } return ( - - - {content} - {this.props.modal} + + + + {content} + {this.props.modal} + ); } diff --git a/web/menu-provider.react.js b/web/menu-provider.react.js new file mode 100644 --- /dev/null +++ b/web/menu-provider.react.js @@ -0,0 +1,79 @@ +// @flow + +import invariant from 'invariant'; +import * as React from 'react'; + +import type { SetState } from 'lib/types/hook-types'; + +import css from './menu.css'; + +type MenuPosition = { + +top: number, + +left: number, +}; +type Props = { + +children: React.Node, +}; +type MenuContextType = { + +renderMenu: SetState, + +setMenuPosition: SetState, + +currentMenu: React.Node, + +closeMenu: React.Node => void, +}; + +const MenuContext: React.Context = React.createContext( + { + renderMenu: () => {}, + setMenuPosition: () => {}, + currentMenu: null, + closeMenu: () => {}, + }, +); + +function MenuProvider(props: Props): React.Node { + const { children } = props; + const [menu, setMenu] = React.useState(null); + const [position, setPosition] = React.useState({ + top: 0, + left: 0, + }); + + const closeMenu = React.useCallback( + (menuToClose: React.Node) => + setMenu(oldMenu => { + if (oldMenu === menuToClose) { + return null; + } else { + return oldMenu; + } + }), + [], + ); + + const value = React.useMemo( + () => ({ + renderMenu: setMenu, + setMenuPosition: setPosition, + currentMenu: menu, + closeMenu, + }), + [closeMenu, menu], + ); + return ( + <> + {children} +
+ {menu} +
+ + ); +} + +function useRenderMenu(): MenuContextType { + const context = React.useContext(MenuContext); + invariant(context, 'MenuContext not found'); + + return context; +} + +export { MenuProvider, useRenderMenu }; diff --git a/web/menu.css b/web/menu.css new file mode 100644 --- /dev/null +++ b/web/menu.css @@ -0,0 +1,3 @@ +div.container { + position: absolute; +}