diff --git a/web/app/components/workflow/nodes/_base/components/__tests__/node-handle.spec.tsx b/web/app/components/workflow/nodes/_base/components/__tests__/node-handle.spec.tsx index 2b0524be69..1f2c3b3aef 100644 --- a/web/app/components/workflow/nodes/_base/components/__tests__/node-handle.spec.tsx +++ b/web/app/components/workflow/nodes/_base/components/__tests__/node-handle.spec.tsx @@ -188,17 +188,19 @@ describe('node-handle', () => { const addNodeButton = getAddNodeButton() expect(addNodeButton).toHaveClass('custom-selector') - expect(addNodeButton).toHaveClass('hidden') + expect(addNodeButton).toHaveClass('opacity-0') expect(addNodeButton).toHaveClass('pointer-events-none') fireEvent.click(addNodeButton) - expect(addNodeButton).toHaveClass('flex!') + expect(addNodeButton).toHaveClass('opacity-100') + // Trigger stays pointer-events-none so it never steals mousedown from + // the underlying React Flow handle (drag-to-connect must keep working). expect(addNodeButton).toHaveClass('pointer-events-none') fireEvent.click(handle) - expect(addNodeButton).toHaveClass('hidden') + expect(addNodeButton).toHaveClass('opacity-0') fireEvent.click(getSelectNodeButton()) @@ -235,7 +237,7 @@ describe('node-handle', () => { selected: true, }) - expect(getAddNodeButton()).toHaveClass('flex!') + expect(getAddNodeButton()).toHaveClass('opacity-100') expect(getAddNodeButton()).toHaveClass('pointer-events-none') }) @@ -261,12 +263,11 @@ describe('node-handle', () => { const handle = screen.getByTestId('handle-source-handle') const addNodeButton = getAddNodeButton() - expect(addNodeButton).toHaveClass('hidden') - expect(addNodeButton).toHaveClass('pointer-events-none') + expect(addNodeButton).toHaveClass('opacity-0') fireEvent.click(addNodeButton) - expect(addNodeButton).toHaveClass('flex!') + expect(addNodeButton).toHaveClass('opacity-100') expect(addNodeButton).toHaveClass('pointer-events-none') fireEvent.click(getSelectNodeButton()) @@ -284,7 +285,7 @@ describe('node-handle', () => { fireEvent.click(handle) - expect(addNodeButton).toHaveClass('hidden') + expect(addNodeButton).toHaveClass('opacity-0') }) it('should keep the source add trigger visible when the node is selected', () => { @@ -295,7 +296,7 @@ describe('node-handle', () => { const addNodeButton = getAddNodeButton() expect(addNodeButton).toHaveClass('custom-selector') - expect(addNodeButton).toHaveClass('flex!') + expect(addNodeButton).toHaveClass('opacity-100') expect(addNodeButton).toHaveClass('pointer-events-none') }) @@ -332,7 +333,7 @@ describe('node-handle', () => { const addNodeButton = getAddNodeButton() - expect(addNodeButton).toHaveClass('flex!') + expect(addNodeButton).toHaveClass('opacity-100') expect(addNodeButton).toHaveClass('pointer-events-none') expect(mockSetShouldAutoOpenStartNodeSelector).toHaveBeenCalledWith(false) expect(mockSetHasSelectedStartNode).toHaveBeenCalledWith(false) @@ -344,7 +345,7 @@ describe('node-handle', () => { renderSourceHandle({ type: BlockEnum.Start }) - expect(getAddNodeButton()).toHaveClass('hidden') + expect(getAddNodeButton()).toHaveClass('opacity-0') expect(mockSetShouldAutoOpenStartNodeSelector).toHaveBeenCalledWith(false) expect(mockSetHasSelectedStartNode).not.toHaveBeenCalled() }) @@ -365,7 +366,7 @@ describe('node-handle', () => { renderSourceHandle({ type: BlockEnum.Code }) - expect(getAddNodeButton()).toHaveClass('hidden') + expect(getAddNodeButton()).toHaveClass('opacity-0') expect(mockSetShouldAutoOpenStartNodeSelector).not.toHaveBeenCalled() expect(mockSetHasSelectedStartNode).not.toHaveBeenCalled() expect(mockWorkflowStoreSetState).not.toHaveBeenCalled() diff --git a/web/app/components/workflow/nodes/_base/components/node-handle.tsx b/web/app/components/workflow/nodes/_base/components/node-handle.tsx index db3ff7a973..58597a1670 100644 --- a/web/app/components/workflow/nodes/_base/components/node-handle.tsx +++ b/web/app/components/workflow/nodes/_base/components/node-handle.tsx @@ -112,13 +112,12 @@ export const NodeTargetHandle = memo(({ onSelect={handleSelect} asChild placement="left" - // Keep the trigger out of hit-testing so drag-to-connect still lands on the React Flow handle. triggerClassName={open => ` - hidden absolute left-0 top-0 pointer-events-none + absolute left-0 top-0 opacity-0 pointer-events-none transition-opacity duration-150 ${nodeSelectorClassName} - group-hover:flex! - ${data.selected && 'flex!'} - ${open && 'flex!'} + group-hover:opacity-100 + ${data.selected && 'opacity-100'} + ${open && 'opacity-100'} `} availableBlocksTypes={availablePrevBlocks} /> @@ -231,13 +230,12 @@ export const NodeSourceHandle = memo(({ onOpenChange={handleOpenChange} onSelect={handleSelect} asChild - // Keep the trigger out of hit-testing so drag-to-connect still lands on the React Flow handle. triggerClassName={open => ` - hidden absolute top-0 left-0 pointer-events-none + absolute top-0 left-0 opacity-0 pointer-events-none transition-opacity duration-150 ${nodeSelectorClassName} - group-hover:flex! - ${data.selected && 'flex!'} - ${open && 'flex!'} + group-hover:opacity-100 + ${data.selected && 'opacity-100'} + ${open && 'opacity-100'} `} availableBlocksTypes={availableNextBlocks} />