threshold

threshold

Require minimum time or distance before dragging starts

The threshold plugin prevents accidental dragging by requiring minimum time delay or distance movement before dragging begins. Essential for touch interfaces and clickable elements to distinguish between taps and drags.

threshold({ distance: 10 }); // Move 10px before dragging starts
threshold({ delay: 200 }); // Wait 200ms before dragging starts
threshold({ distance: 5, delay: 100 }); // Both conditions required
threshold(null); // Disable threshold completely

Basic Usage

<script setup>
import { vDraggable, threshold } from '@neodrag/vue';
</script>

<template>
  <div>
    <div v-draggable="[threshold({ distance: 10 })]">
      Drag after moving 10px
    </div>

    <div v-draggable="[threshold({ delay: 300 })]">
      Hold for 300ms to drag
    </div>

    <div v-draggable="[threshold({ distance: 8, delay: 150 })]">
      Move 8px AND wait 150ms
    </div>

    <div v-draggable="[threshold(null)]">Immediate dragging</div>
  </div>
</template>

Dynamic Thresholds

Adjust thresholds based on device or user preferences:

Common Use Cases

Touch-Friendly Buttons

// Distinguish between taps and drags on touch devices
threshold({
  distance: 10, // Allow some finger movement
  delay: 0, // Start immediately once threshold met
});

Clickable Cards

// Prevent accidental drags when clicking links/buttons
threshold({
  distance: 8, // Require intentional movement
  delay: 100, // Brief hold period
});

Precision Drawing Tools

// High precision for drawing/design apps
threshold({
  distance: 2, // Very sensitive
  delay: 0, // Immediate response
});

Long-Press Drag

// Require long press before dragging (like mobile context menus)
threshold({
  distance: 5, // Small movement tolerance
  delay: 500, // Half-second hold required
});

Device-Specific Recommendations

Mobile/Touch Devices

// Recommended for touch interfaces
threshold({
  distance: 8, // Account for finger imprecision
  delay: 50, // Brief delay helps differentiate from taps
});

Desktop/Mouse

// Recommended for mouse interfaces
threshold({
  distance: 3, // Mice are more precise
  delay: 0, // No delay needed
});

Auto-Detection

// Detect touch capability and adjust accordingly
const isTouchDevice =
  'ontouchstart' in window || navigator.maxTouchPoints > 0;

threshold(
  isTouchDevice
    ? { distance: 10, delay: 100 }
    : { distance: 3, delay: 0 },
);

Combining with Other Plugins

Mobile-Optimized Setup

const plugins = [
  threshold({ distance: 10, delay: 50 }), // Prevent accidents
  scrollLock({ lockAxis: 'both' }), // Prevent scroll interference
  touchAction('none'), // Disable browser gestures
];

With Events

const plugins = [
  threshold({ distance: 8, delay: 200 }),
  events({
    onDragStart: () =>
      console.log('Threshold met - dragging started'),
    // Note: onDrag won't fire until threshold is met
  }),
];

Conditional Threshold

// Only apply threshold in certain modes
const plugins = [
  isEditMode
    ? threshold({ distance: 15, delay: 300 })
    : threshold(null),
  bounds(BoundsFrom.parent()),
];

How It Works

The threshold plugin prevents dragging until conditions are met:

  1. On pointer down (shouldStart):

    • Records start time and position
    • Always returns true (allows interaction)
  2. During movement (drag):

    • Checks if currently dragging (if yes, does nothing)
    • Verifies pointer is still over the draggable element
    • Tests distance: √((currentX - startX)² + (currentY - startY)²)
    • Tests delay: currentTime - startTime
    • Calls ctx.preventStart() if thresholds not met
  3. Both conditions must be satisfied (AND logic):

    • Distance moved ≥ required distance
    • Time elapsed ≥ required delay

Distance calculation:

const deltaX = event.clientX - startPosition.x;
const deltaY = event.clientY - startPosition.y;
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);

Edge case handling:

  • Moving outside the draggable element prevents dragging
  • Invalid values (negative) throw errors during setup
  • null options disable the plugin entirely

API Reference

function threshold(
  options?: {
    distance?: number;
    delay?: number;
  } | null,
): Plugin;

Options:

  • distance - Minimum pixels to move before dragging starts (default: 3)
  • delay - Minimum milliseconds to wait before dragging starts (default: 0)
  • null - Disable threshold checking entirely

Behavior:

  • Both conditions must be met (AND logic)
  • Distance uses Euclidean distance (straight line)
  • Negative values throw errors
  • Empty object {} uses defaults
  • Moving outside element prevents dragging

Returns: A plugin object for use with draggable.