From 086d47d83c2b3075cdbe95771403b2a7e61cbf39 Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Fri, 1 Mar 2024 14:54:39 +0000 Subject: [PATCH] Chore: replace `react-popper` with `floating-ui` in `ExemplarMarker` (#83694) * replace react-popper with floating-ui in ExemplarMarker * fix e2e test * floating-ui uses mousemove --- e2e/various-suite/exemplars.spec.ts | 2 +- package.json | 1 - packages/grafana-ui/package.json | 1 - .../timeseries/plugins/ExemplarMarker.tsx | 102 +++++++++--------- yarn.lock | 4 +- 5 files changed, 50 insertions(+), 60 deletions(-) diff --git a/e2e/various-suite/exemplars.spec.ts b/e2e/various-suite/exemplars.spec.ts index 0a7981b03ac..60f58386520 100644 --- a/e2e/various-suite/exemplars.spec.ts +++ b/e2e/various-suite/exemplars.spec.ts @@ -69,7 +69,7 @@ describe('Exemplars', () => { cy.get(`[data-testid="time-series-zoom-to-data"]`).click(); - e2e.components.DataSource.Prometheus.exemplarMarker().first().trigger('mouseover'); + e2e.components.DataSource.Prometheus.exemplarMarker().first().trigger('mousemove'); cy.contains('Query with gdev-tempo').click(); e2e.components.TraceViewer.spanBar().should('have.length', 11); }); diff --git a/package.json b/package.json index 9182e8a426a..1ac1116a482 100644 --- a/package.json +++ b/package.json @@ -376,7 +376,6 @@ "react-inlinesvg": "3.0.2", "react-loading-skeleton": "3.4.0", "react-moveable": "0.56.0", - "react-popper": "2.3.0", "react-redux": "8.1.3", "react-resizable": "3.0.5", "react-responsive-carousel": "^3.2.23", diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index 69436c7d08c..b9bbc0c10cb 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -93,7 +93,6 @@ "react-i18next": "^12.0.0", "react-inlinesvg": "3.0.2", "react-loading-skeleton": "3.4.0", - "react-popper": "2.3.0", "react-router-dom": "5.3.3", "react-select": "5.8.0", "react-table": "7.8.0", diff --git a/public/app/plugins/panel/timeseries/plugins/ExemplarMarker.tsx b/public/app/plugins/panel/timeseries/plugins/ExemplarMarker.tsx index 6c59f0ad1e2..e1f77808965 100644 --- a/public/app/plugins/panel/timeseries/plugins/ExemplarMarker.tsx +++ b/public/app/plugins/panel/timeseries/plugins/ExemplarMarker.tsx @@ -1,6 +1,15 @@ import { css, cx } from '@emotion/css'; -import React, { CSSProperties, useCallback, useEffect, useRef, useState } from 'react'; -import { usePopper } from 'react-popper'; +import { + autoUpdate, + flip, + safePolygon, + shift, + useDismiss, + useFloating, + useHover, + useInteractions, +} from '@floating-ui/react'; +import React, { CSSProperties, useCallback, useEffect, useState } from 'react'; import { DataFrame, @@ -44,25 +53,34 @@ export const ExemplarMarker = ({ const styles = useStyles2(getExemplarMarkerStyles); const [isOpen, setIsOpen] = useState(false); const [isLocked, setIsLocked] = useState(false); - const [markerElement, setMarkerElement] = React.useState(null); - const [popperElement, setPopperElement] = React.useState(null); - const { styles: popperStyles, attributes } = usePopper(markerElement, popperElement, { - modifiers: [ - { - name: 'preventOverflow', - options: { - altAxis: true, - }, - }, - { - name: 'flip', - options: { - fallbackPlacements: ['top', 'left-start'], - }, - }, - ], + + // the order of middleware is important! + const middleware = [ + flip({ + fallbackAxisSideDirection: 'end', + // see https://floating-ui.com/docs/flip#combining-with-shift + crossAxis: false, + boundary: document.body, + }), + shift(), + ]; + + const { context, refs, floatingStyles } = useFloating({ + open: isOpen, + placement: 'bottom', + onOpenChange: setIsOpen, + middleware, + whileElementsMounted: autoUpdate, + strategy: 'fixed', }); - const popoverRenderTimeout = useRef(); + + const dismiss = useDismiss(context); + const hover = useHover(context, { + handleClose: safePolygon(), + enabled: clickedExemplarFieldIndex === undefined, + }); + + const { getReferenceProps, getFloatingProps } = useInteractions([dismiss, hover]); useEffect(() => { if ( @@ -107,25 +125,10 @@ export const ExemplarMarker = ({ return symbols[dataFrameFieldIndex.frameIndex % symbols.length]; }; - const onMouseEnter = useCallback(() => { - if (clickedExemplarFieldIndex === undefined) { - if (popoverRenderTimeout.current) { - clearTimeout(popoverRenderTimeout.current); - } - setIsOpen(true); - } - }, [setIsOpen, clickedExemplarFieldIndex]); - const lockExemplarModal = () => { setIsLocked(true); }; - const onMouseLeave = useCallback(() => { - popoverRenderTimeout.current = setTimeout(() => { - setIsOpen(false); - }, 150); - }, [setIsOpen]); - const renderMarker = useCallback(() => { //Put fields with links on the top const fieldsWithLinks = @@ -220,28 +223,20 @@ export const ExemplarMarker = ({ }; return ( -
+
{getExemplarMarkerContent()}
); }, [ - attributes.popper, dataFrame.fields, dataFrameFieldIndex, - onMouseEnter, - onMouseLeave, - popperStyles.popper, styles, timeZone, isLocked, setClickedExemplarFieldIndex, + floatingStyles, + getFloatingProps, + refs.setFloating, ]); const seriesColor = config @@ -256,19 +251,18 @@ export const ExemplarMarker = ({ return ( <>
{ if (e.key === 'Enter') { onExemplarClick(); } }} - onMouseEnter={onMouseEnter} - onMouseLeave={onMouseLeave} - className={styles.markerWrapper} - data-testid={selectors.components.DataSource.Prometheus.exemplarMarker} - role="button" - tabIndex={0} >