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>
This commit is contained in:
Abhishek Kumar 2026-05-26 13:15:42 +00:00
parent 317d6b3fab
commit 6292118473
2 changed files with 21 additions and 44 deletions

4
ui/package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "ui",
"version": "1.31.0",
"version": "1.30.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ui",
"version": "1.31.0",
"version": "1.30.1",
"dependencies": {
"@dagrejs/dagre": "^1.1.4",
"@radix-ui/react-alert-dialog": "^1.1.15",

View file

@ -6,7 +6,7 @@ import { useWorkflow, useWorkflowOptional } from "@/app/workflow/[workflowId]/co
import { useWorkflowStore } from "@/app/workflow/[workflowId]/stores/workflowStore";
import { TextOrAudioInput } from "@/components/flow/TextOrAudioInput";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from '@/components/ui/textarea';
@ -157,11 +157,9 @@ export default function CustomEdge(props: CustomEdgeProps) {
const { getEdges, setNodes } = useReactFlow<FlowNode, FlowEdge>();
const { saveWorkflow } = useWorkflow();
const readOnly = useWorkflowOptional()?.readOnly ?? false;
const updateEdge = useWorkflowStore((state) => state.updateEdge);
const deleteEdge = useWorkflowStore((state) => state.deleteEdge);
const [open, setOpen] = useState(false);
const [confirmDeleteOpen, setConfirmDeleteOpen] = useState(false);
const [isHovered, setIsHovered] = useState(false);
const parallel = getEdges().filter(
@ -264,7 +262,6 @@ export default function CustomEdge(props: CustomEdgeProps) {
const handleDeleteEdge = useCallback(async () => {
deleteEdge(id);
setConfirmDeleteOpen(false);
await saveWorkflow();
}, [id, deleteEdge, saveWorkflow]);
@ -330,26 +327,24 @@ export default function CustomEdge(props: CustomEdgeProps) {
<span className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
Condition
</span>
{!readOnly && (
<>
<Button
variant="ghost"
size="icon"
className="h-6 w-6 p-0 hover:bg-destructive/10 hover:text-destructive text-muted-foreground"
onClick={() => setConfirmDeleteOpen(true)}
>
<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 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">
@ -378,24 +373,6 @@ export default function CustomEdge(props: CustomEdgeProps) {
data={data}
onSave={handleSaveEdgeData}
/>
<Dialog open={confirmDeleteOpen} onOpenChange={setConfirmDeleteOpen}>
<DialogContent>
<DialogHeader>
<DialogTitle>Delete Connection</DialogTitle>
<DialogDescription>
Are you sure you want to delete this connection?
</DialogDescription>
</DialogHeader>
<DialogFooter>
<Button variant="outline" onClick={() => setConfirmDeleteOpen(false)}>
Cancel
</Button>
<Button variant="destructive" onClick={handleDeleteEdge}>
Delete
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</>
);
}