diff --git a/web/app.react.js b/web/app.react.js --- a/web/app.react.js +++ b/web/app.react.js @@ -31,6 +31,7 @@ import Chat from './chat/chat.react'; import InputStateContainer from './input/input-state-container.react'; import LoadingIndicator from './loading-indicator.react'; +import { MenuPortalProvider } from './menu-portal-provider.react'; import { ModalProvider, useModalContext } from './modals/modal-provider.react'; import DisconnectedBar from './redux/disconnected-bar'; import DisconnectedBarVisibilityHandler from './redux/disconnected-bar-visibility-handler'; @@ -132,10 +133,12 @@ } return ( - - - {content} - {this.props.modal} + + + + {content} + {this.props.modal} + ); } diff --git a/web/menu-portal-provider.react.js b/web/menu-portal-provider.react.js new file mode 100644 --- /dev/null +++ b/web/menu-portal-provider.react.js @@ -0,0 +1,55 @@ +// @flow + +import invariant from 'invariant'; +import * as React from 'react'; +import ReactDOM from 'react-dom'; + +import css from './menu-portal.css'; + +type Props = { + +children: React.Node, +}; +type MenuPortalContextType = { + +renderInMenuPortal: (itemToRender: React.Node) => void, +}; + +const MenuPortalContext: React.Context = React.createContext( + { + renderInMenuPortal: () => {}, + }, +); + +function MenuPortalProvider(props: Props): React.Node { + const { children } = props; + const portalRef = React.useRef(); + + const renderInMenuPortal = React.useCallback( + (itemToRender: React.Node) => + ReactDOM.createPortal(itemToRender, portalRef.current), + [], + ); + const value = React.useMemo( + () => ({ + renderInMenuPortal, + }), + [renderInMenuPortal], + ); + + return ( + <> + + {children} + +
+ + ); +} + +function useRenderInMenuPortal(): (itemToRender: React.Node) => void { + const context = React.useContext(MenuPortalContext); + invariant(context, 'ModalPortalContext not found'); + + return context.renderInMenuPortal; +} + +export { MenuPortalProvider, useRenderInMenuPortal }; diff --git a/web/menu-portal.css b/web/menu-portal.css new file mode 100644 --- /dev/null +++ b/web/menu-portal.css @@ -0,0 +1,5 @@ +div.portal { + position: absolute; + top: 0; + left: 0; +}