diff --git a/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx b/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx index e9590c434b2..7a18d549315 100644 --- a/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx +++ b/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin2.tsx @@ -288,8 +288,10 @@ export const TooltipPlugin2 = ({ } // only pinnable tooltip is visible *and* is within proximity to series/point else if (_isHovering && closestSeriesIdx != null && !_isPinned) { - _isPinned = true; - scheduleRender(true); + setTimeout(() => { + _isPinned = true; + scheduleRender(true); + }, 0); } } }); @@ -513,8 +515,52 @@ export const TooltipPlugin2 = ({ if (domRef.current != null) { size.observer.observe(domRef.current); + + // since the above observer is attached after container is in DOM, we need to manually update sizeRef + // and re-trigger a cursor move to do initial positioning math + const { width, height } = domRef.current.getBoundingClientRect(); + size.width = width; + size.height = height; + + let event = plot!.cursor.event; + + // if not viaSync, re-dispatch real event + if (event != null) { + // we expect to re-dispatch mousemove, but on mobile we'll get mouseup or click + const isMobile = event.type !== 'mousemove'; + + if (isMobile) { + event = new MouseEvent('mousemove', { + view: window, + bubbles: true, + cancelable: true, + clientX: event.clientX, + clientY: event.clientY, + screenX: event.screenX, + screenY: event.screenY, + }); + } + + // this works around the fact that uPlot does not unset cursor.event (for perf reasons) + // so if the last real mouse event was mouseleave and you manually trigger u.setCursor() + // it would end up re-dispatching mouseleave + const isStaleEvent = isMobile ? false : performance.now() - event.timeStamp > 16; + + !isStaleEvent && plot!.over.dispatchEvent(event); + } else { + plot!.setCursor( + { + left: plot!.cursor.left!, + top: plot!.cursor.top!, + }, + true + ); + } + } else { + size.width = 0; + size.height = 0; } - }, [domRef.current]); + }, [isHovering]); if (plot && isHovering) { return createPortal(