Drag behavior
These inputs change when a drag starts and how it moves. All of them are optional.
Only one drag runs at a time. While an item is being dragged, with the pointer or the keyboard, pressing another item (a second finger on a touch screen) or pressing Space on it does not start a second drag.
Drag handles
Set dragHandle to a CSS selector, and only presses inside a matching element in the row start a drag (an element around the row that matches doesn't count). The rest of the row stays free for selecting text, clicking and so on.
Make the handle a non-interactive element such as a <span>. Presses inside a button in the row never start a drag, as the next section explains. Keyboard dragging is unaffected: the whole row stays focusable.
Interactive children
Controls inside rows keep working: pressing them never starts a drag. What starts a drag depends on where the pointer press lands, or on which element has focus when Space is pressed:
Only controls inside the row count: a control around the list doesn't stop a drag, and neither does a draggable element that is a button (a button, or an input of type button, submit, reset or image). A draggable element that is another control, such as a text field, a checkbox, a select or a [contenteditable] element, keeps its own press and Space: a press focuses, opens, toggles or places the caret, and Space types a space, toggles or opens. An element with contenteditable="false" is not editable, so it doesn't count either.
Rows inside a [contenteditable] editor drag like any other row, so pressing one starts a drag instead of placing the caret. To keep their text editable with the mouse, give them a drag handle. The same goes for blocks that are their own editing host (<div contenteditable vdndDraggable>): give them a handle with contenteditable="false", such as a grip icon, and presses on it start a drag while the rest of the block stays editable. Space in the block's text types a space, so make the grip focusable for keyboard users, with tabindex="0", role="button" and an aria-label such as "Drag block": Space on it picks the block up. Without a focusable handle, the block can't be moved with the keyboard. After a keyboard drop or cancel, focus returns to the block itself (placing the caret in it), so Tab reaches the grip again. In Chromium, Space on a row inside an editor goes to the editor instead of picking the row up; Firefox and Safari pick it up.
Only the primary mouse button starts a drag. To turn dragging off completely, use disabled.
Other interactive elements are not recognized, for example a web component whose input is inside its shadow DOM, or an element with role="switch". Add no-drag to them. For a web component, add it to the component element itself: presses inside its shadow DOM reach the row as presses on that element.
Threshold and delay
When the delay has passed, the element gets the vdnd-drag-pending class. Style it so users can see the item is ready to move:
A delay of 150–250 ms works well on touch devices.
Axis locking
lockAxis names the axis that is frozen:
'x': the X axis is frozen, so the item moves only vertically'y': the Y axis is frozen, so the item moves only horizontally
This is the opposite of CDK's cdkDragLockAxis, where 'x' means the item moves along the X axis.
Constraining to the container
The preview cannot leave the container. Holding it against the container's top or bottom edge drops the item at the first or last position once the list is scrolled to that end; until then the drop position is the visible row at that edge, while autoscroll, when it runs, moves the list there. The container is the nearest vdndScrollable ancestor if there is one, and the droppable otherwise.
When a sticky header or footer inside the vdndScrollable element covers part of it, pass their heights as scrollInsetTop and scrollInsetBottom so the preview stays clear of them (see Sticky headers and footers).
Disabling
Every draggable, droppable and list accepts disabled:
- A disabled draggable cannot be picked up. It gets
tabindex="-1"and thevdnd-draggable-disabledclass. - A disabled droppable (or
<vdnd-sortable-list>) is skipped as a target. Its items can still be dragged out, so for a read-only list also disable the draggables in its item template. The pointer passes through to whatever enabled droppable is underneath, and keyboard left/right navigation skips it. Releasing over it emits no(drop).(dragEnd)still fires withdestinationIndex: null. It gets thevdnd-droppable-disabledclass.