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
import { createSignal } from 'solid-js';
import { threshold, useDraggable } from '@neodrag/solid';
function ThresholdExamples() {
const [distanceRef, setDistanceRef] = createSignal();
const [delayRef, setDelayRef] = createSignal();
const [bothRef, setBothRef] = createSignal();
const [disabledRef, setDisabledRef] = createSignal();
useDraggable(distanceRef, [threshold({ distance: 10 })]);
useDraggable(delayRef, [threshold({ delay: 300 })]);
useDraggable(bothRef, [threshold({ distance: 8, delay: 150 })]);
useDraggable(disabledRef, [threshold(null)]);
return (
<div>
<div ref={setDistanceRef}>Drag after moving 10px</div>
<div ref={setDelayRef}>Hold for 300ms to drag</div>
<div ref={setBothRef}>Move 8px AND wait 150ms</div>
<div ref={setDisabledRef}>Immediate dragging</div>
</div>
);
}
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:
-
On pointer down (
shouldStart
):- Records start time and position
- Always returns
true
(allows interaction)
-
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
-
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.