From 7c562c1d9d4a86459b2b02f6ad17ebc6277aa7e8 Mon Sep 17 00:00:00 2001 From: shrimbly Date: Fri, 27 Feb 2026 22:07:34 +1300 Subject: [PATCH] fix(45): fix ConditionalSwitch handle alignment, drop menu, and default connector Resolve three issues with the Conditional Switch node: - Add fromHandleType resolution for conditionalSwitch in handleConnectEnd so the connection drop menu appears when dragging from rule/default outputs - Align output handles with visual rule rows by accounting for the text preview height in baseOffset and using fixed h-8 rows matching handleSpacing=32 - Move "Add Rule" button after the Default row so the default handle aligns with its visual row instead of being displaced Co-Authored-By: Claude Opus 4.6 --- src/components/WorkflowCanvas.tsx | 5 ++ .../nodes/ConditionalSwitchNode.tsx | 50 +++++++++---------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/src/components/WorkflowCanvas.tsx b/src/components/WorkflowCanvas.tsx index 5cac779a..47286220 100644 --- a/src/components/WorkflowCanvas.tsx +++ b/src/components/WorkflowCanvas.tsx @@ -606,6 +606,11 @@ export function WorkflowCanvas() { } } + // ConditionalSwitch output handles have dynamic IDs (rule-xxx, default) — always text type + if (!fromHandleType && connectionState.fromNode.type === "conditionalSwitch") { + fromHandleType = "text"; + } + // Helper to find a compatible handle on a node by type const findCompatibleHandle = ( node: Node, diff --git a/src/components/nodes/ConditionalSwitchNode.tsx b/src/components/nodes/ConditionalSwitchNode.tsx index a748618e..c7f0d7ca 100644 --- a/src/components/nodes/ConditionalSwitchNode.tsx +++ b/src/components/nodes/ConditionalSwitchNode.tsx @@ -82,13 +82,14 @@ export const ConditionalSwitchNode = memo(({ id, data, selected }: NodeProps { @@ -205,14 +206,14 @@ export const ConditionalSwitchNode = memo(({ id, data, selected }: NodeProps - {/* Input handle (left) - text only */} + {/* Input handle (left) - text only, aligned with header */} {/* Body content */} -
- {/* Text preview */} -
+
+ {/* Text preview — fixed height, above the handle-aligned area */} +
{incomingText ? ( <>Input: "{incomingText.slice(0, 50)}{incomingText.length > 50 ? "..." : ""}" ) : ( @@ -231,18 +232,16 @@ export const ConditionalSwitchNode = memo(({ id, data, selected }: NodeProps - {/* Rule rows */} + {/* Rule rows — each 32px tall to align with output handles */} {nodeData.rules.map((rule, index) => ( -
+
{/* Match status indicator */}
{rule.isMatched ? ( - // Green checkmark ) : ( - // Gray dot
)}
@@ -333,34 +332,31 @@ export const ConditionalSwitchNode = memo(({ id, data, selected }: NodeProps ))} - {/* Add rule button */} - - - {/* Default output row */} -
- {/* Match status indicator */} + {/* Default output row — 32px tall, immediately after rules to align with handle */} +
{defaultMatched ? ( - // Green checkmark ) : ( - // Gray dot
)}
Default
+ + {/* Add rule button — after Default so it doesn't displace handle alignment */} +
{/* Output handles (right) - one per rule + default */}