mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
TooltipPlugin2: Raise parent grid item z-index when pinned (#76379)
This commit is contained in:
parent
4dfffa3c32
commit
94c15e4926
@ -1092,6 +1092,9 @@ exports[`better eslint`] = {
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"],
|
||||
[0, 0, 0, "Do not use any type assertions.", "1"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx:5381": [
|
||||
[0, 0, 0, "Do not use any type assertions.", "0"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/uPlot/types.ts:5381": [
|
||||
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
|
||||
],
|
||||
|
@ -5,14 +5,13 @@ import uPlot from 'uplot';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
import { useStyles2 } from '../../../themes/ThemeContext';
|
||||
import { useStyles2 } from '../../../themes';
|
||||
import { UPlotConfigBuilder } from '../config/UPlotConfigBuilder';
|
||||
|
||||
import { CloseButton } from './CloseButton';
|
||||
|
||||
interface TooltipPlugin2Props {
|
||||
config: UPlotConfigBuilder;
|
||||
// or via .children() render prop callback?
|
||||
render: (
|
||||
u: uPlot,
|
||||
dataIdxs: Array<number | null>,
|
||||
@ -67,7 +66,7 @@ export const TooltipPlugin2 = ({ config, render }: TooltipPlugin2Props) => {
|
||||
|
||||
const sizeRef = useRef<TooltipContainerSize>();
|
||||
|
||||
const className = useStyles2(getStyles).tooltipWrapper;
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
sizeRef.current = {
|
||||
@ -108,8 +107,9 @@ export const TooltipPlugin2 = ({ config, render }: TooltipPlugin2Props) => {
|
||||
let closestSeriesIdx: number | null = null;
|
||||
|
||||
let pendingRender = false;
|
||||
let pendingPinned = false;
|
||||
|
||||
const scheduleRender = () => {
|
||||
const scheduleRender = (setPinned = false) => {
|
||||
if (!pendingRender) {
|
||||
// defer unrender for 100ms to reduce flickering in small gaps
|
||||
if (!_isHovering) {
|
||||
@ -120,11 +120,43 @@ export const TooltipPlugin2 = ({ config, render }: TooltipPlugin2Props) => {
|
||||
|
||||
pendingRender = true;
|
||||
}
|
||||
|
||||
if (setPinned) {
|
||||
pendingPinned = true;
|
||||
}
|
||||
};
|
||||
|
||||
// in some ways this is similar to ClickOutsideWrapper.tsx
|
||||
const downEventOutside = (e: Event) => {
|
||||
let isOutside = (e.target as HTMLDivElement).closest(`.${styles.tooltipWrapper}`) !== domRef.current;
|
||||
|
||||
if (isOutside) {
|
||||
dismiss();
|
||||
}
|
||||
};
|
||||
|
||||
const _render = () => {
|
||||
pendingRender = false;
|
||||
|
||||
if (pendingPinned) {
|
||||
_style = { pointerEvents: _isPinned ? 'all' : 'none' };
|
||||
|
||||
domRef.current!.closest<HTMLDivElement>('.react-grid-item')?.classList.toggle('context-menu-open', _isPinned);
|
||||
|
||||
// @ts-ignore
|
||||
_plot!.cursor._lock = _isPinned;
|
||||
|
||||
if (_isPinned) {
|
||||
document.addEventListener('mousedown', downEventOutside, true);
|
||||
document.addEventListener('keydown', downEventOutside, true);
|
||||
} else {
|
||||
document.removeEventListener('mousedown', downEventOutside, true);
|
||||
document.removeEventListener('keydown', downEventOutside, true);
|
||||
}
|
||||
|
||||
pendingPinned = false;
|
||||
}
|
||||
|
||||
let state: TooltipContainerState = {
|
||||
style: _style,
|
||||
isPinned: _isPinned,
|
||||
@ -139,35 +171,18 @@ export const TooltipPlugin2 = ({ config, render }: TooltipPlugin2Props) => {
|
||||
const dismiss = () => {
|
||||
_isPinned = false;
|
||||
_isHovering = false;
|
||||
_style = { pointerEvents: 'none' };
|
||||
|
||||
// @ts-ignore
|
||||
_plot!.cursor._lock = _isPinned;
|
||||
|
||||
scheduleRender();
|
||||
_plot!.setCursor({ left: -10, top: -10 });
|
||||
scheduleRender(true);
|
||||
};
|
||||
|
||||
config.addHook('init', (u) => {
|
||||
setState({ plot: (_plot = u) });
|
||||
|
||||
// TODO: use cursor.lock & and mousedown/mouseup here (to prevent unlocking)
|
||||
// this handles pinning
|
||||
u.over.addEventListener('click', (e) => {
|
||||
if (_isHovering) {
|
||||
if (e.target === u.over) {
|
||||
_isPinned = !_isPinned;
|
||||
_style = { pointerEvents: _isPinned ? 'all' : 'none' };
|
||||
scheduleRender();
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
u.cursor._lock = _isPinned;
|
||||
|
||||
// hack to trigger cursor to new position after unlock
|
||||
// (should not be necessary after using the cursor.lock API)
|
||||
if (!_isPinned) {
|
||||
u.setCursor({ left: e.clientX - u.rect.left, top: e.clientY - u.rect.top });
|
||||
_isHovering = false;
|
||||
}
|
||||
if (_isHovering && !_isPinned && e.target === u.over) {
|
||||
_isPinned = true;
|
||||
scheduleRender(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -268,7 +283,7 @@ export const TooltipPlugin2 = ({ config, render }: TooltipPlugin2Props) => {
|
||||
|
||||
if (plot && isHovering) {
|
||||
return createPortal(
|
||||
<div className={className} style={style} ref={domRef}>
|
||||
<div className={styles.tooltipWrapper} style={style} ref={domRef}>
|
||||
{isPinned && <CloseButton onClick={dismiss} style={{ top: '16px' }} />}
|
||||
{contents}
|
||||
</div>,
|
||||
@ -290,5 +305,6 @@ const getStyles = (theme: GrafanaTheme2) => ({
|
||||
position: 'absolute',
|
||||
background: theme.colors.background.secondary,
|
||||
boxShadow: `0 4px 8px ${theme.colors.background.primary}`,
|
||||
userSelect: 'text',
|
||||
}),
|
||||
});
|
||||
|
@ -87,7 +87,7 @@
|
||||
}
|
||||
|
||||
// Hack to prevent panel overlap during drag/hover (due to descending z-index assignment)
|
||||
.react-grid-item {
|
||||
.react-grid-item:not(.context-menu-open, .resizing) {
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
@ -96,10 +96,12 @@
|
||||
}
|
||||
|
||||
// Hack for preventing panel menu overlapping.
|
||||
.react-grid-item.context-menu-open,
|
||||
.react-grid-item.resizing,
|
||||
.react-grid-item.resizing.panel,
|
||||
.react-grid-item.panel.dropdown-menu-open,
|
||||
.react-grid-item.react-draggable-dragging.panel {
|
||||
z-index: $zindex-dropdown;
|
||||
z-index: $zindex-dropdown !important;
|
||||
}
|
||||
|
||||
// Disable animation on initial rendering and enable it when component has been mounted.
|
||||
|
Loading…
Reference in New Issue
Block a user