From e81f116f4fce995624b06766773504934c7e4641 Mon Sep 17 00:00:00 2001 From: lapidus Date: Mon, 3 Jun 2024 10:55:35 +0200 Subject: [PATCH] Update tooltip to account for iframe offsets --- .../visx-xychart/src/components/Tooltip.tsx | 56 +++++++++++++++++-- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/packages/visx-xychart/src/components/Tooltip.tsx b/packages/visx-xychart/src/components/Tooltip.tsx index f5a763d6a..59fcdb513 100644 --- a/packages/visx-xychart/src/components/Tooltip.tsx +++ b/packages/visx-xychart/src/components/Tooltip.tsx @@ -93,6 +93,22 @@ function defaultRenderGlyph(props: RenderTooltipGlyphProps return ; } +function getIframeOffsets(target) { + let offsetX = 0; + let offsetY = 0; + let currentWindow = target.ownerDocument.defaultView; + + while (currentWindow && currentWindow.frameElement) { + const frameElement = currentWindow.frameElement; + const frameRect = frameElement.getBoundingClientRect(); + offsetX += frameRect.left; + offsetY += frameRect.top; + currentWindow = currentWindow.parent; + } + + return { x: offsetX, y: offsetY }; +} + function TooltipInner({ debounce, detectBounds, @@ -132,15 +148,46 @@ function TooltipInner({ zIndex, }); + function getIframeOffsets(target) { + let offsetX = 0; + let offsetY = 0; + let currentWindow = target.ownerDocument.defaultView; + + while (currentWindow && currentWindow.frameElement) { + const frameElement = currentWindow.frameElement; + const frameRect = frameElement.getBoundingClientRect(); + offsetX += frameRect.left; + offsetY += frameRect.top; + currentWindow = currentWindow.parent; + } + + return { x: offsetX, y: offsetY }; + } + // To correctly position itself in a Portal, the tooltip must know its container bounds // this is done by rendering an invisible node whose ref can be used to find its parentElement const setContainerRef = useCallback( (ownRef: HTMLElement | SVGElement | null) => { - containerRef(ownRef?.parentElement ?? null); + if (ownRef && ownRef.parentElement instanceof Element) { + const iframeOffsets = getIframeOffsets(ownRef); + const parentRect = ownRef.parentElement.getBoundingClientRect(); + const adjustedContainer = { + ...ownRef.parentElement, + getBoundingClientRect: () => ({ + ...parentRect, + x: parentRect.x + iframeOffsets.x, + y: parentRect.y + iframeOffsets.y, + left: parentRect.left + iframeOffsets.x, + top: parentRect.top + iframeOffsets.y, + }), + }; + containerRef(adjustedContainer); + } else { + containerRef(null); + } }, [containerRef], ); - const tooltipContent = tooltipContext?.tooltipOpen ? renderTooltip({ ...tooltipContext, colorScale }) : null; @@ -301,10 +348,9 @@ function TooltipInner({ )} - {glyphProps.map(({ x, y, ...props }, i) => ( - // We render glyps in a portal so that they can overflow the container if necessary + {glyphProps.map(({ key, x, y, ...props }) => (