feat: add delete button in an edge in workflow builder (#366)

* Added delete option for edge between two nodes

* Removed extra stack dump file

* chore: advance pipecat submodule to include MiniMax LLM service

* updated pipecat to c771a50e

* fix: simplify edge delete to match node and Backspace UX

Drop the confirmation dialog: node delete and Backspace-on-edge both
delete immediately and rely on undo/redo. The trash button should
behave the same way.

Match the GenericNode toolbar pattern by always rendering the trash
and pencil buttons (no readOnly gate); the edit dialog already
disables Save in readOnly. Wrap the two buttons in a flex container
with a small gap so they don't sit flush against each other.

Revert the manual package-lock version bump; that field is owned by
release-please.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: don't auto-save on edge delete

Persisting the workflow is a separate intent from "delete this edge",
the same way it's separate from "delete this node" (useNodeHandlers
doesn't auto-save either). The Save button in the edit dialog conveys
the save semantics; trash buttons shouldn't piggy-back on them.

After this, all delete paths (node toolbar trash, edge toolbar trash,
Backspace on node, Backspace on edge) mark the workflow dirty and
leave persistence to Cmd+S or the header Save button.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: XI <xman.india@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Abhishek 2026-05-26 19:00:01 +05:30 committed by GitHub
parent 3df5730076
commit 9675151549
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,5 +1,5 @@
import { BaseEdge, type Edge, EdgeLabelRenderer, type EdgeProps, getSmoothStepPath, useReactFlow } from '@xyflow/react';
import { AlertCircle, Pencil } from 'lucide-react';
import { AlertCircle, Pencil, Trash2 } from 'lucide-react';
import { useCallback, useEffect, useState } from 'react';
import { useWorkflow, useWorkflowOptional } from "@/app/workflow/[workflowId]/contexts/WorkflowContext";
@ -158,6 +158,7 @@ export default function CustomEdge(props: CustomEdgeProps) {
const { getEdges, setNodes } = useReactFlow<FlowNode, FlowEdge>();
const { saveWorkflow } = useWorkflow();
const updateEdge = useWorkflowStore((state) => state.updateEdge);
const deleteEdge = useWorkflowStore((state) => state.deleteEdge);
const [open, setOpen] = useState(false);
const [isHovered, setIsHovered] = useState(false);
@ -259,6 +260,10 @@ export default function CustomEdge(props: CustomEdgeProps) {
await saveWorkflow();
}, [id, updateEdge, saveWorkflow]);
const handleDeleteEdge = useCallback(() => {
deleteEdge(id);
}, [id, deleteEdge]);
return (
<>
<g
@ -321,14 +326,24 @@ export default function CustomEdge(props: CustomEdgeProps) {
<span className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
Condition
</span>
<Button
variant="ghost"
size="icon"
className="h-6 w-6 p-0 hover:bg-muted text-muted-foreground"
onClick={() => setOpen(true)}
>
<Pencil className="h-3 w-3" />
</Button>
<div className="flex items-center gap-1">
<Button
variant="ghost"
size="icon"
className="h-6 w-6 p-0 hover:bg-destructive/10 hover:text-destructive text-muted-foreground"
onClick={handleDeleteEdge}
>
<Trash2 className="h-3 w-3" />
</Button>
<Button
variant="ghost"
size="icon"
className="h-6 w-6 p-0 hover:bg-muted text-muted-foreground"
onClick={() => setOpen(true)}
>
<Pencil className="h-3 w-3" />
</Button>
</div>
</div>
{/* Content */}
<div className="px-3 pb-3">