From dd41c7c2621c9610589961c8dae2d339537bd28c Mon Sep 17 00:00:00 2001 From: Andrej Ocenas Date: Mon, 17 Jul 2023 22:29:39 +0200 Subject: [PATCH] Flamegraph: Fix wrong positioning of tooltip in dashboards (#71396) --- .../components/FlameGraph/FlameGraph.tsx | 29 ++------ .../FlameGraph/FlameGraphTooltip.tsx | 67 ++++++++----------- 2 files changed, 33 insertions(+), 63 deletions(-) diff --git a/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.tsx b/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.tsx index 56f928a2919..e8031b66eb9 100644 --- a/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.tsx +++ b/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.tsx @@ -83,7 +83,6 @@ const FlameGraph = ({ const [sizeRef, { width: wrapperWidth }] = useMeasure(); const graphRef = useRef(null); - const tooltipRef = useRef(null); const [tooltipItem, setTooltipItem] = useState(); const [clickedItemData, setClickedItemData] = useState(); @@ -132,10 +131,12 @@ const FlameGraph = ({ [data, rangeMin, rangeMax, totalTicks, levels] ); + const [mousePosition, setMousePosition] = useState<{ x: number; y: number }>(); const onGraphMouseMove = useCallback( (e: ReactMouseEvent) => { - if (tooltipRef.current && clickedItemData === undefined) { + if (clickedItemData === undefined) { setTooltipItem(undefined); + setMousePosition(undefined); const pixelsPerTick = graphRef.current!.clientWidth / totalTicks / (rangeMax - rangeMin); const { levelIndex, barIndex } = convertPixelCoordinatesToBarCoordinates( { x: e.nativeEvent.offsetX, y: e.nativeEvent.offsetY }, @@ -146,30 +147,12 @@ const FlameGraph = ({ ); if (barIndex !== -1 && !isNaN(levelIndex) && !isNaN(barIndex)) { - // tooltip has a set number of lines of text so 200 should be good enough (with some buffer) without going - // into measuring rendered sizes - if (e.clientY < document.documentElement.clientHeight - 200) { - tooltipRef.current.style.top = e.clientY + 'px'; - tooltipRef.current.style.bottom = 'auto'; - } else { - tooltipRef.current.style.bottom = document.documentElement.clientHeight - e.clientY + 'px'; - tooltipRef.current.style.top = 'auto'; - } - - // 400 is max width of the tooltip - if (e.clientX < document.documentElement.clientWidth - 400) { - tooltipRef.current.style.left = e.clientX + 15 + 'px'; - tooltipRef.current.style.right = 'auto'; - } else { - tooltipRef.current.style.right = document.documentElement.clientWidth - e.clientX + 15 + 'px'; - tooltipRef.current.style.left = 'auto'; - } - + setMousePosition({ x: e.clientX, y: e.clientY }); setTooltipItem(levels[levelIndex][barIndex]); } } }, - [rangeMin, rangeMax, totalTicks, clickedItemData, levels] + [rangeMin, rangeMax, totalTicks, clickedItemData, levels, setMousePosition] ); const onGraphMouseLeave = useCallback(() => { @@ -224,7 +207,7 @@ const FlameGraph = ({ /> - + {clickedItemData && ( ; }; -const FlameGraphTooltip = ({ data, tooltipRef, item, totalTicks }: Props) => { +const FlameGraphTooltip = ({ data, item, totalTicks, position }: Props) => { const styles = useStyles2(getStyles); - let content = null; - if (item) { - const tooltipData = getTooltipData(data, item, totalTicks); - content = ( -
-

{data.getLabel(item.itemIndexes[0])}

-

- {tooltipData.unitTitle} -
- Total: {tooltipData.unitValue} ({tooltipData.percentValue}%) -
- Self: {tooltipData.unitSelf} ({tooltipData.percentSelf}%) -
- Samples: {tooltipData.samples} -

-
- ); + if (!(item && position)) { + return null; } - // Even if we don't show tooltip we need this div so the ref is consistently attached. Would need some refactor in - // FlameGraph.tsx to make it work without it. - return ( -
- {content} + const tooltipData = getTooltipData(data, item, totalTicks); + const content = ( +
+

{data.getLabel(item.itemIndexes[0])}

+

+ {tooltipData.unitTitle} +
+ Total: {tooltipData.unitValue} ({tooltipData.percentValue}%) +
+ Self: {tooltipData.unitSelf} ({tooltipData.percentSelf}%) +
+ Samples: {tooltipData.samples} +

); + + return ( + + + {content} + + + ); }; type TooltipData = { @@ -87,23 +88,9 @@ export const getTooltipData = (data: FlameGraphDataContainer, item: LevelItem, t }; const getStyles = (theme: GrafanaTheme2) => ({ - tooltip: css` - title: tooltip; - position: fixed; - z-index: ${theme.zIndex.tooltip}; - `, tooltipContent: css` title: tooltipContent; - background-color: ${theme.components.tooltip.background}; - border-radius: ${theme.shape.radius.default}; - border: 1px solid ${theme.components.tooltip.background}; - box-shadow: ${theme.shadows.z2}; - color: ${theme.components.tooltip.text}; font-size: ${theme.typography.bodySmall.fontSize}; - padding: ${theme.spacing(0.5, 1)}; - transition: opacity 0.3s; - max-width: 400px; - overflow-wrap: break-word; `, lastParagraph: css` title: lastParagraph;