Imagine you have a form inside a draggable element in your application. We could simply set the draggable="true"
attribute on the outer most element and then and it is draggable.
But making a DOM element draggable like this also means that all child elements act as a “source” of dragging. For some mouse gestures, such as highlighting text, this is problematic because the gesture is mistaken for dragging the parent element.

A better UX option is a “drag handle”: A specific child element that provides a cue for the dragging interaction, and that mediates when dragging of the parent element happens.

What I did was only set draggable="true"
on outerDraggable
when the grab handle gets a mousedown
event.
dragHandle.addEventListener("mousedown", ()=>{
outerDraggable.setAttribute("draggable", "true");
});
Then in the drop
and dragend
event handlers, I removed the draggable
attribute from outerDraggable
so that it “settles” and doesn’t misinterpret post-drag, drag-like mouse gestures unless the drag handle is “activated” with a mouse down.
Ensuring this happens on mousedown
has the neat effect that you naturally drag the element “by” the handle. In reality, you could “click” the handle … then drag from anywhere in the element. This is actually a behaviour we want to keep, because not everyone is dragging with a mouse.
Simple but effective.