Inspired by this example in the react-flow docs, I created my own version which opens a Material Ui Popper once the edge is selected. My issue is that while the popper stays perfectly anchored to the edge's button while I'm dragging nodes around, when I try to zoom or pan the react-flow surface the popper get's detached from the anchor.
Here is a sandbox reproducing the issue, and here is the relevant piece of code:
import React, { useState, useRef, useEffect } from "react";
import { getBezierPath } from "reactflow";
import { Fade, Paper, Popper } from "@mui/material";
import "./index.css";
const foreignObjectSize = 40;
export default function CustomEdge({
id,
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition,
style = {},
markerEnd,
selected
}) {
const [edgePath, labelX, labelY] = getBezierPath({
sourceX,
sourceY,
sourcePosition,
targetX,
targetY,
targetPosition
});
const [isPopperOpen, setIsPopperOpen] = useState(false);
const anchorElementRef = useRef();
useEffect(() => {
if (selected) {
setTimeout(() => setIsPopperOpen(true), 350);
}
}, [selected]);
return (
<>
<path
id={id}
style={style}
className="react-flow__edge-path"
d={edgePath}
markerEnd={markerEnd}
/>
<foreignObject
width={foreignObjectSize}
height={foreignObjectSize}
x={labelX - foreignObjectSize / 2}
y={labelY - foreignObjectSize / 2}
className="edgebutton-foreignobject"
requiredExtensions="http://www.w3.org/1999/xhtml"
>
<div ref={anchorElementRef}>
<button className="edgebutton">×</button>
<Popper
open={isPopperOpen}
anchorEl={anchorElementRef.current}
placement="top"
transition
>
{({ TransitionProps }) => (
<Fade {...TransitionProps} timeout={350}>
<Paper style={{ padding: 15 }}>Helo popper!</Paper>
</Fade>
)}
</Popper>
</div>
</foreignObject>
</>
);
}
Any help would be greatly appreciated.
Try putting
disablePortal={true}
prop onPopper
. This should inject the popper directly into DOM structure, and so couple with the proper (node/edge) element.