Browse Source

feat(44-03): apply CSS-based visual dimming to nodes

- Subscribe to dimmedNodeIds in WorkflowCanvas
- Apply switch-dimmed className in allNodes useMemo
- Exclude Switch nodes from dimming (they stay fully visible)
- Added CSS: 40% opacity with 250ms transition
- Transition applies in both directions (dimming and un-dimming)
- Dimming updates reactively when toggles or edges change
handoff-20260429-1057
shrimbly 5 months ago
parent
commit
0fb3347b16
  1. 10
      src/app/globals.css
  2. 22
      src/components/WorkflowCanvas.tsx

10
src/app/globals.css

@ -49,6 +49,16 @@ body {
box-shadow: none !important;
}
/* Switch dimming - nodes downstream of disabled Switch outputs */
.react-flow__node.switch-dimmed {
opacity: 0.4;
transition: opacity 250ms ease-in-out;
}
.react-flow__node:not(.switch-dimmed) {
transition: opacity 250ms ease-in-out;
}
/* Base handle styles */
.react-flow__handle {
width: 10px;

22
src/components/WorkflowCanvas.tsx

@ -251,7 +251,7 @@ const findScrollableAncestor = (target: HTMLElement, deltaX: number, deltaY: num
};
export function WorkflowCanvas() {
const { nodes, edges, groups, onNodesChange, onEdgesChange, onConnect, addNode, updateNodeData, loadWorkflow, getNodeById, addToGlobalHistory, setNodeGroupId, executeWorkflow, isModalOpen, showQuickstart, setShowQuickstart, navigationTarget, setNavigationTarget, captureSnapshot, applyEditOperations, setWorkflowMetadata, canvasNavigationSettings, setShortcutsDialogOpen } =
const { nodes, edges, groups, onNodesChange, onEdgesChange, onConnect, addNode, updateNodeData, loadWorkflow, getNodeById, addToGlobalHistory, setNodeGroupId, executeWorkflow, isModalOpen, showQuickstart, setShowQuickstart, navigationTarget, setNavigationTarget, captureSnapshot, applyEditOperations, setWorkflowMetadata, canvasNavigationSettings, setShortcutsDialogOpen, dimmedNodeIds } =
useWorkflowStore();
const { screenToFlowPosition, getViewport, zoomIn, zoomOut, setViewport, setCenter } = useReactFlow();
const { show: showToast } = useToast();
@ -286,10 +286,24 @@ export function WorkflowCanvas() {
}
}, [navigationTarget, nodes, setCenter, setNavigationTarget]);
// Just pass regular nodes to React Flow - groups are rendered separately
// Apply dimming className to nodes downstream of disabled Switch outputs
const allNodes = useMemo(() => {
return nodes;
}, [nodes]);
return nodes.map((node) => {
// Never dim Switch nodes themselves
if (node.type === "switch") return node;
const isDimmed = dimmedNodeIds.has(node.id);
const dimClass = isDimmed ? "switch-dimmed" : "";
// Preserve existing className if any, add/remove dimmed class
const baseClass = (node.className || "").replace(/\bswitch-dimmed\b/g, "").trim();
const newClass = dimClass ? `${baseClass} ${dimClass}`.trim() : baseClass;
// Only create new node object if className changed
if (node.className === newClass) return node;
return { ...node, className: newClass };
});
}, [nodes, dimmedNodeIds]);
// Check if a node was dropped into a group and add it to that group

Loading…
Cancel
Save