mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Performance: Create separate div for portal root to limit reflow -> recalc style (#47633)
* Performance: Create separate div for portal root to limit reflow -> recalc style * refactoring
This commit is contained in:
parent
a4381ebc91
commit
6042beab43
@ -9,9 +9,11 @@ interface Props {
|
||||
}
|
||||
|
||||
export function Portal(props: PropsWithChildren<Props>) {
|
||||
const { children, className, root: portalRoot = document.body, forwardedRef } = props;
|
||||
const { children, className, root, forwardedRef } = props;
|
||||
const theme = useTheme2();
|
||||
const node = useRef<HTMLDivElement | null>(null);
|
||||
const portalRoot = root ?? getPortalContainer();
|
||||
|
||||
if (!node.current) {
|
||||
node.current = document.createElement('div');
|
||||
if (className) {
|
||||
@ -25,6 +27,7 @@ export function Portal(props: PropsWithChildren<Props>) {
|
||||
if (node.current) {
|
||||
portalRoot.appendChild(node.current);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (node.current) {
|
||||
portalRoot.removeChild(node.current);
|
||||
@ -35,7 +38,18 @@ export function Portal(props: PropsWithChildren<Props>) {
|
||||
return ReactDOM.createPortal(<div ref={forwardedRef}>{children}</div>, node.current);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function getPortalContainer() {
|
||||
return window.document.getElementById('grafana-portal-container') ?? document.body;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function PortalContainer() {
|
||||
return <div id="grafana-portal-container" />;
|
||||
}
|
||||
|
||||
export const RefForwardingPortal = React.forwardRef<HTMLDivElement, Props>((props, ref) => {
|
||||
return <Portal {...props} forwardedRef={ref} />;
|
||||
});
|
||||
|
||||
RefForwardingPortal.displayName = 'RefForwardingPortal';
|
||||
|
@ -6,7 +6,7 @@ export { Tooltip } from './Tooltip/Tooltip';
|
||||
export { PopoverContent } from './Tooltip/types';
|
||||
export { PopoverController } from './Tooltip/PopoverController';
|
||||
export { Popover } from './Tooltip/Popover';
|
||||
export { Portal } from './Portal/Portal';
|
||||
export { Portal, getPortalContainer, PortalContainer } from './Portal/Portal';
|
||||
export { CustomScrollbar, ScrollbarPosition } from './CustomScrollbar/CustomScrollbar';
|
||||
export { TabbedContainer, TabConfig } from './TabbedContainer/TabbedContainer';
|
||||
|
||||
|
@ -3,7 +3,7 @@ import { Router, Route, Redirect, Switch } from 'react-router-dom';
|
||||
import { config, locationService, navigationLogger } from '@grafana/runtime';
|
||||
import { Provider } from 'react-redux';
|
||||
import { store } from 'app/store/store';
|
||||
import { ErrorBoundaryAlert, GlobalStyles, ModalRoot, ModalsProvider } from '@grafana/ui';
|
||||
import { ErrorBoundaryAlert, GlobalStyles, ModalRoot, ModalsProvider, PortalContainer } from '@grafana/ui';
|
||||
import { GrafanaApp } from './app';
|
||||
import { getAppRoutes } from 'app/routes/routes';
|
||||
import { ConfigContext, ThemeProvider } from './core/utils/ConfigProvider';
|
||||
@ -113,6 +113,7 @@ export class AppWrapper extends React.Component<AppWrapperProps, AppWrapperState
|
||||
</div>
|
||||
<LiveConnectionWarning />
|
||||
<ModalRoot />
|
||||
<PortalContainer />
|
||||
</ModalsProvider>
|
||||
</ThemeProvider>
|
||||
</ConfigContext.Provider>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { ReactElement, useEffect, useState } from 'react';
|
||||
import { css, cx } from '@emotion/css';
|
||||
import { Icon, IconName, Link, useTheme2 } from '@grafana/ui';
|
||||
import { getPortalContainer, Icon, IconName, Link, useTheme2 } from '@grafana/ui';
|
||||
import { GrafanaTheme2, NavModelItem } from '@grafana/data';
|
||||
import { MenuTriggerProps } from '@react-types/menu';
|
||||
import { useMenuTriggerState } from '@react-stately/menu';
|
||||
@ -182,7 +182,7 @@ export function NavBarItemMenuTrigger(props: NavBarItemMenuTriggerProps): ReactE
|
||||
<div className={cx(styles.element, 'dropdown')} {...focusWithinProps} {...hoverProps}>
|
||||
{element}
|
||||
{state.isOpen && (
|
||||
<OverlayContainer>
|
||||
<OverlayContainer portalContainer={getPortalContainer()}>
|
||||
<NavBarItemMenuContext.Provider
|
||||
value={{
|
||||
menuProps,
|
||||
|
Loading…
Reference in New Issue
Block a user