Skip to content

Handles, Filters & Touch ​

Drag handles ​

Restrict drag starts to a grip inside each item with a CSS selector:

vue
<Draggable v-model="items" handle=".grip" item-key="id">
  <template #item="{ element }">
    <div class="row">
      <span class="grip">⋮⋮</span>
      <span>{{ element.name }}</span>
    </div>
  </template>
</Draggable>

Handles are the recommended pattern for lists containing text (it stays selectable) and for long lists on mobile (users can still scroll by touching outside the grip).

Filters ​

Block drags that start on interactive children:

ts
{ filter: 'button, input, a' }

preventOnFilter (default true) also calls preventDefault() on the filtered pointerdown; set it to false if your inputs need native focus behaviour.

Which items are draggable ​

By default every indexed child is draggable. Restrict with a selector items must match:

ts
{ draggable: ':not(.locked)' }

Items failing the selector still render they just can't be picked up (drops can still land around them).

Touch delay (long-press to drag) ​

Instant drags fight scrolling on touch screens. A delay turns the gesture into long-press-to-drag:

ts
{
  delay: 200,               // ms before the drag arms
  delayOnTouchOnly: true,   // default  mouse/pen drags stay instant
  touchStartThreshold: 6,   // px of drift allowed during the delay
}

A quick tap-and-swipe scrolls the page normally; holding for 200 ms picks the item up.

Drag threshold ​

With no delay, a drag begins once the pointer travels dragThreshold px (default 5). Raise it if clicks are being eaten on jittery input devices.

Disabling ​

disabled: true switches off every interaction on the list pointer, keyboard and selection while leaving your rendering untouched.

Released under the MIT License.