axis
Restrict movement to a single axis (x or y)
The axis
plugin locks movement to horizontal (x
) or vertical (y
) direction. Perfect for sliders, scrollbars, or any UI requiring one-dimensional dragging.
axis('x'); // Only horizontal movement
axis('y'); // Only vertical movement
axis(null); // Free movement (removes constraint)
Basic Usage
import { createSignal } from 'solid-js';
import { axis, useDraggable } from '@neodrag/solid';
function AxisExamples() {
const [horizontalRef, setHorizontalRef] =
createSignal<HTMLElement | null>(null);
const [verticalRef, setVerticalRef] =
createSignal<HTMLElement | null>(null);
const [freeRef, setFreeRef] = createSignal<HTMLElement | null>(
null,
);
useDraggable(horizontalRef, [axis('x')]);
useDraggable(verticalRef, [axis('y')]);
useDraggable(freeRef, [axis(null)]);
return (
<div>
<div ref={setHorizontalRef}>Horizontal only</div>
<div ref={setVerticalRef}>Vertical only</div>
<div ref={setFreeRef}>Any direction</div>
</div>
);
}
Dynamic Axis Switching
import { createSignal } from 'solid-js';
import {
axis,
useDraggable,
createCompartment,
} from '@neodrag/solid';
function DynamicAxis() {
const [ref, setRef] = createSignal<HTMLElement | null>(null);
const [currentAxis, setCurrentAxis] = createSignal<'x' | 'y'>('x');
const axisComp = createCompartment(() => axis(currentAxis()));
useDraggable(ref, [axisComp]);
function switchAxis() {
setCurrentAxis(currentAxis() === 'x' ? 'y' : 'x');
}
return (
<div>
<div ref={setRef}>
Currently locked to: {currentAxis()} axis
</div>
<button onClick={switchAxis}>
Switch to {currentAxis() === 'x' ? 'Y' : 'X'} axis
</button>
</div>
);
}
Real-World Examples
Horizontal Slider Component
import { createSignal } from 'solid-js';
import {
axis,
bounds,
BoundsFrom,
events,
useDraggable,
} from '@neodrag/solid';
function Slider() {
const [track, setTrack] = createSignal<HTMLElement | null>(null);
const [handle, setHandle] = createSignal<HTMLElement | null>(null);
const [value, setValue] = createSignal(50);
const handleDrag = (data) => {
if (track()) {
const trackWidth = track()!.offsetWidth;
setValue(Math.round((data.offset.x / trackWidth) * 100));
}
};
useDraggable(handle, [
axis('x'),
bounds(() => BoundsFrom.element(track()!)),
events({ onDrag: handleDrag }),
]);
return (
<div>
<div ref={setTrack} class="track">
<div ref={setHandle} class="handle" />
</div>
<p>Value: {value()}%</p>
</div>
);
}
Split Pane Resizer
// Vertical divider for horizontal split
const plugins = [
axis('x'),
bounds(
BoundsFrom.parent({
left: 100, // Min pane width
right: 100, // Min pane width
}),
),
];
How It Works
The axis plugin modifies the proposed
movement during dragging:
axis('x')
: Setsproposed.y = null
(no vertical movement)axis('y')
: Setsproposed.x = null
(no horizontal movement)axis(null)
: No changes (free movement)
This happens in the plugin’s drag
hook, so other plugins receive the constrained movement values.
API Reference
function axis(value?: 'x' | 'y' | null | undefined): Plugin;
Parameters:
value
- The axis to constrain movement to'x'
- Horizontal only'y'
- Vertical onlynull
orundefined
- No constraint
Returns: A plugin object for use with draggable.