Edge lines sometimes overlay edge labels
See original GitHub issueDescribe the Bug
In some cases edge lines will overlay the edge labels, which looks bad and can cause readability issues. Whether or not this happens depends on the rendering order of the edges in the final svg.
Your Example Website or App
https://reactflow.dev/docs/examples/edges/custom-edge/
Steps to Reproduce the Bug or Issue
- Go To: https://reactflow.dev/docs/examples/edges/custom-edge/
- Notice how the
label with styled bg
box is behind the line forcustom edge
Expected behavior
As a user, I expect custom edge content to be rendered above the edge lines, so that none of the content in the edges gets hidden, and for better visual appeal.
Screenshots or Videos
Platform
- OS: macOS
- Browser: Chrome
- Version: 106.0.5249.103
Additional context
There is a clear explanation of svg z-index and rendering order here: https://stackoverflow.com/a/25302276/2373122.
I created a small script that fixes the overlay issue on the example page that I referenced. We can run this in our app, but it’s not ideal to do dom surgery every time reactflow renders. Life would be much better if reactflow was careful to render all the edge lines before
the edges themselves so that the lines do not overlay actual content. With the current structure of the custom edges, I don’t know exactly how this would be implemented. I might be missing something here, perhaps there’s an easier way to accomplish what we need, but I wanted to pose the issue anyway and see where it goes.
Also worth noting, someone else reported this issue as a discussion, but there was no response there: https://github.com/wbkd/react-flow/discussions/2250. They were on an older version of reactflow, but I am on the current version (v11).
const edgeClass = 'react-flow__edge';
const edgePathClass = 'react-flow__edge-path';
const edges = [...document.querySelectorAll(`.${edgeClass}`)];
if (edges.length === 0) {
return;
}
const edgesContainer = edges[0].parentElement;
edges.forEach((edge) => {
const edgeText = edge.querySelector('text');
const edgePath = edge.querySelector(`.${edgePathClass}`);
if (!edgeText || !edgePath) {
return;
}
const clonedEdge = edge.cloneNode(true);
clonedEdge.querySelector(`.${edgePathClass}`).remove();
edgesContainer.append(clonedEdge);
edgeText.remove();
});
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:6 (6 by maintainers)
Top GitHub Comments
This is a very first draft, but I could imagine that it could work: https://codesandbox.io/s/portaledgelabelrenderer-ikxqkb?file=/ButtonEdge.js . In this example the edge label is just a div. No
foreignObject
needed. The edge labels get rendered to a separate EdgeLabelRenderer component with the help of a Portal.We could export a component (
EdgeLabelRenderer
) that one could use as a helper component to render a label to a dedicated edge-label-renderer dom node as seen in the example.I would love to have a separated div based renderer for the edge labels. I will try to find out if this is possible with the current structure.