This is an example of a custom edge implementation with a button. In order to leave SVG world we are using foreignObject inside the custom edge to be able to use <button>.
Edge With Button Source Code
index.js
import React, { useState } from 'react';
import ReactFlow, {
removeElements,
addEdge,
MiniMap,
Controls,
Background,
} from 'react-flow-renderer';
import ButtonEdge from './ButtonEdge';
const onLoad = (reactFlowInstance) => reactFlowInstance.fitView();
const initialElements = [
{
id: 'ewb-1',
type: 'input',
data: { label: 'Input 1' },
position: { x: 250, y: 0 },
},
{ id: 'ewb-2', data: { label: 'Node 2' }, position: { x: 250, y: 300 } },
{
id: 'edge-1-2',
source: 'ewb-1',
target: 'ewb-2',
type: 'buttonedge',
},
];
const edgeTypes = {
buttonedge: ButtonEdge,
};
const EdgeWithButtonFlow = () => {
const [elements, setElements] = useState(initialElements);
const onElementsRemove = (elementsToRemove) =>
setElements((els) => removeElements(elementsToRemove, els));
const onConnect = (params) =>
setElements((els) => addEdge({ ...params, type: 'buttonedge' }, els));
return (
<ReactFlow
elements={elements}
onElementsRemove={onElementsRemove}
onConnect={onConnect}
snapToGrid={true}
edgeTypes={edgeTypes}
onLoad={onLoad}
key="edge-with-button"
>
<MiniMap />
<Controls />
<Background />
</ReactFlow>
);
};
export default EdgeWithButtonFlow;
ButtonEdge.js
import React from 'react';
import {
getBezierPath,
getEdgeCenter,
getMarkerEnd,
} from 'react-flow-renderer';
import './index.css';
const foreignObjectSize = 40;
const onEdgeClick = (evt, id) => {
evt.stopPropagation();
alert(`remove ${id}`);
};
export default function CustomEdge({
id,
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition,
style = {},
data,
arrowHeadType,
markerEndId,
}) {
const edgePath = getBezierPath({
sourceX,
sourceY,
sourcePosition,
targetX,
targetY,
targetPosition,
});
const markerEnd = getMarkerEnd(arrowHeadType, markerEndId);
const [edgeCenterX, edgeCenterY] = getEdgeCenter({
sourceX,
sourceY,
targetX,
targetY,
});
return (
<>
<path
id={id}
style={style}
className="react-flow__edge-path"
d={edgePath}
markerEnd={markerEnd}
/>
<foreignObject
width={foreignObjectSize}
height={foreignObjectSize}
x={edgeCenterX - foreignObjectSize / 2}
y={edgeCenterY - foreignObjectSize / 2}
className="edgebutton-foreignobject"
requiredExtensions="http://www.w3.org/1999/xhtml"
>
<body>
<button
className="edgebutton"
onClick={(event) => onEdgeClick(event, id)}
>
×
</button>
</body>
</foreignObject>
</>
);
}