diff --git a/frontend/src/components/MessageInput.tsx b/frontend/src/components/MessageInput.tsx index 320cea31..46d3e7d8 100644 --- a/frontend/src/components/MessageInput.tsx +++ b/frontend/src/components/MessageInput.tsx @@ -271,9 +271,12 @@ export default function MessageInput({ // no preview object URLs to revoke (preview removed per reviewer request) - const findIndexById = (id: string) => attachments.findIndex((a) => a.id === id); + const findIndexById = (id: string) => + attachments.findIndex((a) => a.id === id); const handleDragStart = (e: React.DragEvent, id: string) => { + // Prevent parent dropzones from reacting to this drag + e.stopPropagation(); setDraggingId(id); try { e.dataTransfer.setData('text/plain', id); @@ -284,11 +287,15 @@ export default function MessageInput({ }; const handleDragOver = (e: React.DragEvent) => { + // Prevent parent dropzones from triggering + e.stopPropagation(); e.preventDefault(); e.dataTransfer.dropEffect = 'move'; }; const handleDropOn = (e: React.DragEvent, targetId: string) => { + // Prevent parent dropzones from handling this drop + e.stopPropagation(); e.preventDefault(); const sourceId = e.dataTransfer.getData('text/plain'); if (!sourceId || sourceId === targetId) return; @@ -301,6 +308,12 @@ export default function MessageInput({ setDraggingId(null); }; + const handleDragEnd = (e: React.DragEvent) => { + // ensure drag state cleared and do not bubble + e.stopPropagation(); + setDraggingId(null); + }; + return (