fix: use explicit source+hidden-target handles for reliable bidirectional snapping
source handles: visible, can initiate drag from top or bottom target handles: invisible (opacity:0, 12x12px), overlap the source at same position — React Flow detects them for snapping and shows visual feedback without the user seeing a second dot. Ensures bottom→top connections work.
This commit is contained in:
@@ -38,8 +38,8 @@ export function BaseNode({ data, selected, icon: typeIcon }: BaseNodeProps) {
|
|||||||
minWidth: 140,
|
minWidth: 140,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Handle type="source" position={Position.Top} className="!bg-[#30363d] !border-[#8b949e]" />
|
<Handle type="source" position={Position.Top} id="top" className="!bg-[#30363d] !border-[#8b949e]" />
|
||||||
<Handle type="target" position={Position.Top} className="!bg-[#30363d] !border-[#8b949e]" />
|
<Handle type="target" position={Position.Top} id="top-t" style={{ opacity: 0, width: 12, height: 12 }} />
|
||||||
|
|
||||||
{/* Icon */}
|
{/* Icon */}
|
||||||
<div
|
<div
|
||||||
@@ -68,8 +68,8 @@ export function BaseNode({ data, selected, icon: typeIcon }: BaseNodeProps) {
|
|||||||
title={data.status}
|
title={data.status}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Handle type="source" position={Position.Bottom} className="!bg-[#30363d] !border-[#8b949e]" />
|
<Handle type="source" position={Position.Bottom} id="bottom" className="!bg-[#30363d] !border-[#8b949e]" />
|
||||||
<Handle type="target" position={Position.Bottom} className="!bg-[#30363d] !border-[#8b949e]" />
|
<Handle type="target" position={Position.Bottom} id="bottom-t" style={{ opacity: 0, width: 12, height: 12 }} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,10 +80,10 @@ export function ProxmoxGroupNode(props: NodeProps<Node<NodeData>>) {
|
|||||||
<div className="flex-1 relative" />
|
<div className="flex-1 relative" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Handle type="source" position={Position.Top} className="!bg-[#30363d] !border-[#8b949e]" />
|
<Handle type="source" position={Position.Top} id="top" className="!bg-[#30363d] !border-[#8b949e]" />
|
||||||
<Handle type="target" position={Position.Top} className="!bg-[#30363d] !border-[#8b949e]" />
|
<Handle type="target" position={Position.Top} id="top-t" style={{ opacity: 0, width: 12, height: 12 }} />
|
||||||
<Handle type="source" position={Position.Bottom} className="!bg-[#30363d] !border-[#8b949e]" />
|
<Handle type="source" position={Position.Bottom} id="bottom" className="!bg-[#30363d] !border-[#8b949e]" />
|
||||||
<Handle type="target" position={Position.Bottom} className="!bg-[#30363d] !border-[#8b949e]" />
|
<Handle type="target" position={Position.Bottom} id="bottom-t" style={{ opacity: 0, width: 12, height: 12 }} />
|
||||||
|
|
||||||
{/* Cluster handles — left/right for same-cluster links */}
|
{/* Cluster handles — left/right for same-cluster links */}
|
||||||
<Handle type="source" position={Position.Left} id="cluster-left" title="Same cluster" style={{ background: '#ff6e00', borderColor: '#ff6e0088', width: 6, height: 6 }} />
|
<Handle type="source" position={Position.Left} id="cluster-left" title="Same cluster" style={{ background: '#ff6e00', borderColor: '#ff6e0088', width: 6, height: 6 }} />
|
||||||
|
|||||||
Reference in New Issue
Block a user