touchAction
Control browser touch gesture handling
The touchAction
plugin controls browser touch gesture handling on draggable elements. Sets the CSS touch-action
property to prevent conflicts between dragging and browser behaviors like scrolling, zooming, or context menus.
touchAction('manipulation'); // Default - allow basic gestures, disable others
touchAction('none'); // Disable all browser touch behaviors
touchAction('pan-y'); // Allow vertical scrolling only
touchAction(false); // Don't set touch-action (browser default)
Note: TouchAction is included by default with
'manipulation'
mode for optimal touch device compatibility.
Basic Usage
import { useRef } from 'react';
import { touchAction, useDraggable } from '@neodrag/react';
function TouchActionExamples() {
const manipulationRef = useRef<HTMLDivElement>(null);
const noneRef = useRef<HTMLDivElement>(null);
const panYRef = useRef<HTMLDivElement>(null);
const defaultRef = useRef<HTMLDivElement>(null);
useDraggable(manipulationRef, [touchAction('manipulation')]);
useDraggable(noneRef, [touchAction('none')]);
useDraggable(panYRef, [touchAction('pan-y')]);
useDraggable(defaultRef, [touchAction(false)]);
return (
<div>
<div ref={manipulationRef}>Touch-optimized dragging</div>
<div ref={noneRef}>Pure drag only</div>
<div ref={panYRef}>Vertical scroll + drag</div>
<div ref={defaultRef}>Browser default behavior</div>
</div>
);
}
Touch Action Values
Recommended Values
touchAction('manipulation'); // Best for most draggable elements
touchAction('none'); // Complete touch gesture control
touchAction('pan-y'); // Vertical scrolling allowed
touchAction('pan-x'); // Horizontal scrolling allowed
All Available Values
// Basic gestures
touchAction('auto'); // Browser default behavior
touchAction('none'); // Disable all touch behaviors
touchAction('manipulation'); // Allow pan and zoom, disable others
// Directional panning
touchAction('pan-x'); // Horizontal panning only
touchAction('pan-y'); // Vertical panning only
touchAction('pan-left'); // Left panning only
touchAction('pan-right'); // Right panning only
touchAction('pan-up'); // Up panning only
touchAction('pan-down'); // Down panning only
// Zoom control
touchAction('pinch-zoom'); // Pinch-to-zoom only
// CSS globals
touchAction('inherit'); // Inherit from parent
touchAction('initial'); // CSS initial value
touchAction('unset'); // CSS unset value
// Disable plugin
touchAction(false); // Don't set touch-action property
touchAction(null); // Same as false
Dynamic Configuration
import { useRef, useState } from 'react';
import {
touchAction,
useDraggable,
useCompartment,
} from '@neodrag/react';
function DynamicTouchAction() {
const elementRef = useRef<HTMLDivElement>(null);
const [mode, setMode] = useState('manipulation');
const [allowScroll, setAllowScroll] = useState(false);
const touchActionComp = useCompartment(() => {
if (mode === 'disabled') return touchAction(false);
if (allowScroll) return touchAction('pan-y');
return touchAction(mode);
}, [mode, allowScroll]);
useDraggable(elementRef, [touchActionComp]);
const getCurrentValue = () => {
if (mode === 'disabled') return 'not set';
if (allowScroll) return 'pan-y';
return mode;
};
return (
<div>
<div ref={elementRef}>
Current mode: {mode}
{allowScroll ? ' (scroll enabled)' : ''}
</div>
<div className="controls">
<select
value={mode}
onChange={(e) => setMode(e.target.value)}
>
<option value="manipulation">Manipulation</option>
<option value="none">None</option>
<option value="auto">Auto</option>
<option value="disabled">Disabled</option>
</select>
<label>
<input
type="checkbox"
checked={allowScroll}
onChange={(e) => setAllowScroll(e.target.checked)}
/>
Force vertical scroll
</label>
</div>
<p>CSS: touch-action: {getCurrentValue()}</p>
</div>
);
}
Device-Specific Usage
Mobile Phones
// Recommended for mobile drag interfaces
touchAction('manipulation'); // Allows pinch-zoom, prevents conflicts
// For full-screen drag experiences
touchAction('none'); // Complete gesture control
Tablets
// Allow some scrolling while dragging
touchAction('pan-y'); // Vertical scrolling + drag
// General purpose
touchAction('manipulation'); // Good default
Desktop with Touch
// Usually less restrictive
touchAction('auto'); // Browser default often works
// For precision drag tools
touchAction('none'); // Disable browser interference
Common Use Cases
Modal/Dialog Dragging
// Allow page interaction while dragging modal
touchAction('manipulation'); // Keep pinch-zoom, disable pan
Slider/Range Controls
// Horizontal slider that allows vertical scrolling
touchAction('pan-y'); // Only vertical page scrolling
Game/Interactive Elements
// Complete gesture control for games
touchAction('none'); // Disable all browser behaviors
Canvas/Drawing Applications
// High precision drawing
touchAction('none'); // Disable all browser gestures
Combining with Other Plugins
Mobile-Optimized Setup
const plugins = [
touchAction('none'), // Disable browser gestures
threshold({ distance: 8, delay: 50 }), // Prevent accidental drags
scrollLock({ lockAxis: 'both' }), // Prevent page scrolling
];
Context-Aware Setup
const isMobile = /Mobi|Android/i.test(navigator.userAgent);
const isFullScreen = document.fullscreenElement !== null;
const plugins = [
touchAction(isFullScreen ? 'none' : 'manipulation'),
isMobile
? threshold({ distance: 10, delay: 100 })
: threshold({ distance: 3, delay: 0 }),
];
Canvas/Drawing Setup
const plugins = [
touchAction('none'), // Disable all browser gestures
threshold({ distance: 1 }), // Very sensitive
scrollLock({ lockAxis: 'both' }), // Lock scrolling completely
];
Browser Support
Modern Browsers
All modern browsers support touch-action:
- iOS Safari 9.1+
- Chrome 36+
- Firefox 52+
- Edge 12+
Legacy Fallbacks
For older browsers, touch-action is ignored gracefully:
// Graceful degradation
touchAction('manipulation'); // Newer browsers get optimization
// Older browsers fall back to default behavior
iOS Considerations
iOS Safari has specific behaviors:
// iOS often requires 'manipulation' for best results
touchAction('manipulation'); // Works well on iOS
// 'none' can be aggressive on iOS
touchAction('none'); // Use carefully on iOS
How It Works
The touchAction plugin sets the CSS touch-action
property:
- Setup phase: Sets
element.style.touchAction = value
- Browser behavior: Browser respects the property for touch gesture handling
- Live updates: Can change touch-action during drag if needed
CSS Applied:
/* Example results */
.draggable {
touch-action: manipulation;
}
.no-gestures {
touch-action: none;
}
.vertical-scroll {
touch-action: pan-y;
}
What touch-action controls:
- Pan gestures (scrolling)
- Pinch-to-zoom
- Double-tap to zoom
- Context menus (long press)
- Text selection
- Browser navigation gestures
API Reference
function touchAction(mode?: TouchActionMode | false | null): Plugin;
Parameters:
mode
- The touch-action CSS value to apply (default:'manipulation'
)
TouchActionMode values:
'auto'
- Browser default behavior'none'
- Disable all touch behaviors'manipulation'
- Allow pan and zoom, disable others'pan-x'
- Horizontal panning only'pan-y'
- Vertical panning only'pan-left'
,'pan-right'
,'pan-up'
,'pan-down'
- Directional panning'pinch-zoom'
- Pinch-to-zoom only'inherit'
,'initial'
,'unset'
- CSS global valuesfalse
ornull
- Don’t set touch-action (browser default)
Behavior:
- Non-cancelable - always applies the CSS property
- Supports live updates during drag
- Only sets CSS property in setup phase
- Works on all modern browsers with graceful degradation
Returns: A plugin object for use with draggable.