Draggable
Overview
Draggable is a headless @vyui/core primitive that turns its child into a draggable element via a main-thread pan gesture. It is the building block behind Sortable and other drag-driven interactions, and tracks the finger natively for smooth motion.
@vyui/core primitive — a 2D pan gesture over Lynx main-thread touch events. Behavior only, no styles.Usage
<script setup lang="ts">
import { Draggable } from '@vyui/core'
function onEnd(payload) {
console.log('settled at', payload.x, payload.y)
}
</script>
<template>
<Draggable
axis="both"
:bounds="{ left: -120, right: 120, top: -80, bottom: 80 }"
reset-on-end
@drag-end="onEnd"
>
<view class="size-16 rounded-xl bg-primary" />
</Draggable>
</template>
Features and behavior
axislocks dragging to'x','y', or'both'(free 2D pan).boundsconstrains the drag in px relative to the origin; an omitted side is unbounded.resetOnEndanimates back to(0, 0)on release (durationtunes the animation).momentumcarries release velocity into a decelerating coast (clamped tobounds); ignored whenresetOnEndis set.momentumDecelcontrols how quickly the fling stops.emitMoveopts into adrag-moveevent on every touchmove;drag-startanddrag-endalways fire.
API
Props
| Prop | Default | Type |
|---|---|---|
axis | "both" | DraggableAxis | undefinedLock drag to a single axis. `'both'` allows free 2D pan. |
bounds | — | DraggableBounds | undefinedBounds in px relative to the drag origin. Omitted side = unbounded. |
disabled | false | boolean | undefinedDisable interaction. |
duration | 220 | number | undefinedReset animation duration in ms. Only used when `resetOnEnd` is `true`. |
emitMove | false | boolean | undefinedEmit `drag-move` on every touchmove. Off by default. |
momentum | false | boolean | undefinedCarry release velocity into a momentum coast: a flick keeps gliding and decelerates to rest (clamped to `bounds`) instead of stopping dead at the finger. Ignored when `resetOnEnd` is `true` (reset wins). Off by default. |
momentumDecel | 5 | number | undefinedDeceleration rate for `momentum`. Higher = shorter fling. Projected coast distance is `velocity / decel`. |
resetOnEnd | false | boolean | undefinedAnimate back to `(0, 0)` on release. |
Emits
| Event | Payload |
|---|---|
dragStart | [DraggablePosition] |
dragMove | [DragMovePayload] |
dragEnd | [DragEndPayload] |
The drag-move payload adds dx / dy (delta from touchstart); drag-end additionally carries vx / vy release velocity in px/s.
Accessibility
- Pointer dragging has no keyboard equivalent — provide an alternative control path for keyboard and assistive-tech users where the interaction is essential.
Platform notes
- The gesture is implemented with main-thread (MTS) touch worklets, so tracking stays smooth independent of the background thread.