Skip to content

Commit

Permalink
DashboardGrid: Add LayoutItemContext to affect zIndex from panels (#8…
Browse files Browse the repository at this point in the history
  • Loading branch information
leeoniya committed Jan 10, 2024
1 parent 796ef05 commit 31921bb
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 5 deletions.
21 changes: 21 additions & 0 deletions packages/grafana-ui/src/components/Layout/LayoutItemContext.ts
@@ -0,0 +1,21 @@
import { createContext } from 'react';

export interface LayoutItemContextProps {
boostZIndex(): () => void;
}

/**
* Provides an API for downstream components (e.g. within panels) to inform the layout
* that anchored tooltips or context menus could overflow the panel bounds. The layout
* system can then boost the z-index of items with any anchored contents to prevent the overflown
* content from rendering underneath adjacent layout items (e.g. other panels) that naturally
* render later/higher in the stacking order
*
* This is used by VizTooltips and Annotations, which anchor to data points or time range within
* the viz drawing area
*
* @internal
*/
export const LayoutItemContext = createContext<LayoutItemContextProps>({
boostZIndex: () => () => {},
});
2 changes: 2 additions & 0 deletions packages/grafana-ui/src/components/index.ts
Expand Up @@ -264,6 +264,8 @@ export { Avatar } from './UsersIndicator/Avatar';
export { InlineFormLabel } from './FormLabel/FormLabel';
export { Divider } from './Divider/Divider';

export { LayoutItemContext, type LayoutItemContextProps } from './Layout/LayoutItemContext';

/** @deprecated Please use non-legacy versions of these components */
const LegacyForms = {
SecretFormField,
Expand Down
34 changes: 29 additions & 5 deletions public/app/features/dashboard/dashgrid/DashboardGrid.tsx
@@ -1,10 +1,12 @@
import classNames from 'classnames';
import React, { PureComponent, CSSProperties } from 'react';
import React, { PureComponent, CSSProperties, useRef, useCallback, useReducer, useMemo } from 'react';
import ReactGridLayout, { ItemCallback } from 'react-grid-layout';
import AutoSizer from 'react-virtualized-auto-sizer';
import { Subscription } from 'rxjs';

import { zIndex } from '@grafana/data/src/themes/zIndex';
import { config } from '@grafana/runtime';
import { LayoutItemContext } from '@grafana/ui';
import appEvents from 'app/core/app_events';
import { GRID_CELL_HEIGHT, GRID_CELL_VMARGIN, GRID_COLUMN_COUNT } from 'app/core/constants';
import { contextSrv } from 'app/core/services/context_srv';
Expand Down Expand Up @@ -383,6 +385,21 @@ const GrafanaGridItem = React.forwardRef<HTMLDivElement, GrafanaGridItemProps>((
let width = 100;
let height = 100;

const boostedCount = useRef(0);
const [_, forceUpdate] = useReducer((x) => x + 1, 0);

const boostZIndex = useCallback(() => {
boostedCount.current += 1;
forceUpdate();

return () => {
boostedCount.current -= 1;
forceUpdate();
};
}, [forceUpdate]);

const ctxValue = useMemo(() => ({ boostZIndex }), [boostZIndex]);

const { gridWidth, gridPos, isViewing, windowHeight, windowWidth, descendingOrderIndex, ...divProps } = props;
const style: CSSProperties = props.style ?? {};

Expand Down Expand Up @@ -413,10 +430,17 @@ const GrafanaGridItem = React.forwardRef<HTMLDivElement, GrafanaGridItemProps>((

// props.children[0] is our main children. RGL adds the drag handle at props.children[1]
return (
<div {...divProps} style={{ ...divProps.style, zIndex: descendingOrderIndex }} ref={ref}>
{/* Pass width and height to children as render props */}
{[props.children[0](width, height), props.children.slice(1)]}
</div>
<LayoutItemContext.Provider value={ctxValue}>
<div
{...divProps}
// .context-menu-open === $zindex-dropdown === 1030 (zIndex.ts)
style={{ ...divProps.style, zIndex: boostedCount.current === 0 ? descendingOrderIndex : zIndex.dropdown }}
ref={ref}
>
{/* Pass width and height to children as render props */}
{[props.children[0](width, height), props.children.slice(1)]}
</div>
</LayoutItemContext.Provider>
);
});

Expand Down

0 comments on commit 31921bb

Please sign in to comment.