Moveable
A drag wrapper for any element. Position anything freely on the page with mouse, touch, or keyboard — with bounds, axis lock, grid snapping, drag handles, and optional position persistence.
Basic Usage
Wrap any element. Drag with the mouse / touch, or focus the element and press arrow keys.
Basic Drag
Click and drag anywhere on the wrapped element. Tab to focus, then use arrow keys to move.
import { Moveable } from 'fluxo-ui';
<Moveable defaultPosition={{ x: 0, y: 0 }} bounds="parent">
<div className="p-4 bg-bg-subtle border rounded">Drag me</div>
</Moveable>Drag Handle & Axis Lock
Use handleSelector to restrict drag start to a header, and axis to lock to x or y.
Drag Handle & Axis Lock
Use handleSelector to restrict drag start to a header, cancelSelector to exclude inner buttons/inputs, and axis to lock to one direction.
<Moveable
handleSelector=".my-handle"
cancelSelector="button"
axis="x"
bounds="parent"
>
<div className="card">
<div className="my-handle">::: drag here :::</div>
<p>Body — not draggable.</p>
<button>Action — clicks pass through</button>
</div>
</Moveable>Grid Snap
Use grid={[stepX, stepY]} for crisp, aligned positioning.
Grid Snap & Bounds
Drag snaps to a 40-pixel grid while staying inside the parent.
<Moveable
defaultPosition={{ x: 0, y: 0 }}
bounds="parent"
grid={[40, 40]}
snapToGrid
>
<div>Snaps to 40px grid</div>
</Moveable>Compose with Resizable
Wrap a Resizable inside a Moveable to build a floating, sizeable panel — the same primitives the DashboardLayout uses.
Compose with Resizable
Wrap a Resizable inside a Moveable to get a floating panel that can be both dragged and resized — the same primitives the DashboardLayout uses.
// Compose Moveable + Resizable for a floating, sizeable widget
<Moveable defaultPosition={{ x: 24, y: 24 }} bounds="parent" handleSelector=".eui-demo-handle">
<Resizable defaultWidth={260} defaultHeight={160} minWidth={140} minHeight={100}>
<div className="card">
<div className="eui-demo-handle">Drag</div>
<p>Resizable + movable</p>
</div>
</Resizable>
</Moveable>Import
import { Moveable } from 'fluxo-ui';
import type { MoveableProps, MoveablePosition } from 'fluxo-ui';Moveable Props
childrenreqReact.ReactNodeElement(s) wrapped by the movable container.
childrenreqReact.ReactNodeElement(s) wrapped by the movable container.
defaultPosition{ x: number; y: number }"{ x: 0, y: 0 }"Initial position (uncontrolled). Translated relative to the wrapper's CSS origin.
defaultPosition{ x: number; y: number }"{ x: 0, y: 0 }"Initial position (uncontrolled). Translated relative to the wrapper's CSS origin.
position{ x: number; y: number }Controlled position. Provide together with `onPositionChange`.
position{ x: number; y: number }Controlled position. Provide together with `onPositionChange`.
onPositionChange(pos: { x: number; y: number }) => voidFires on every position change (mouse, touch, keyboard).
onPositionChange(pos: { x: number; y: number }) => voidFires on every position change (mouse, touch, keyboard).
onMoveStart(event: MoveableStartEvent) => voidFires when a drag/keypress sequence begins.
onMoveStart(event: MoveableStartEvent) => voidFires when a drag/keypress sequence begins.
onMove(event: MoveableMoveEvent) => voidFires continuously while moving.
onMove(event: MoveableMoveEvent) => voidFires continuously while moving.
onMoveEnd(event: MoveableEndEvent) => voidFires when the move gesture ends.
onMoveEnd(event: MoveableEndEvent) => voidFires when the move gesture ends.
axis'both' | 'x' | 'y'"'both'"Restrict movement to a single axis.
axis'both' | 'x' | 'y'"'both'"Restrict movement to a single axis.
bounds'parent' | 'window' | 'none' | { left, top, right, bottom }"'none'"Confine movement. Numeric bounds are translate-space offsets (not CSS coords).
bounds'parent' | 'window' | 'none' | { left, top, right, bottom }"'none'"Confine movement. Numeric bounds are translate-space offsets (not CSS coords).
grid[number, number]Snap position to a [stepX, stepY] grid (requires `snapToGrid`).
grid[number, number]Snap position to a [stepX, stepY] grid (requires `snapToGrid`).
disabledboolean"false"Disable all interaction.
disabledboolean"false"Disable all interaction.
handleSelectorstringCSS selector for an inner handle. If set, drags only start when the pointer is on a matching element.
handleSelectorstringCSS selector for an inner handle. If set, drags only start when the pointer is on a matching element.
cancelSelectorstringCSS selector for inner elements that should NOT initiate drag (buttons, inputs, etc.).
cancelSelectorstringCSS selector for inner elements that should NOT initiate drag (buttons, inputs, etc.).
cursorstring"'move'"Cursor used while dragging.
cursorstring"'move'"Cursor used while dragging.
snapToGridboolean"true"Apply the `grid` snap. Ignored if `grid` is unset.
snapToGridboolean"true"Apply the `grid` snap. Ignored if `grid` is unset.
keyboardStepnumber"8"Pixels per arrow-key press when the wrapper is focused.
keyboardStepnumber"8"Pixels per arrow-key press when the wrapper is focused.
keyboardBigStepnumber"32"Pixels per Shift+arrow press.
keyboardBigStepnumber"32"Pixels per Shift+arrow press.
elevateOnDragboolean"true"Add `z-index` + shadow while dragging.
elevateOnDragboolean"true"Add `z-index` + shadow while dragging.
rememberLastPositionboolean"false"Persist the last position to `localStorage` (requires `storageKey`).
rememberLastPositionboolean"false"Persist the last position to `localStorage` (requires `storageKey`).
storageKeystringlocalStorage key for `rememberLastPosition`.
storageKeystringlocalStorage key for `rememberLastPosition`.
classNamestringClass name applied to the outer wrapper.
classNamestringClass name applied to the outer wrapper.
styleReact.CSSPropertiesInline styles for the wrapper.
styleReact.CSSPropertiesInline styles for the wrapper.
ariaLabelstring"'Movable element'"Accessible name for the draggable wrapper.
ariaLabelstring"'Movable element'"Accessible name for the draggable wrapper.
Features
Wraps Any Element
Turn any React node into a draggable element with a single wrapper.
Bounds Aware
Keep movement inside the parent, the window, or a custom rect.
Drag Handle Support
Restrict drag start to a specific child via handleSelector.
Axis Lock
Restrict movement to the x-axis or y-axis.
Grid Snap
Provide [stepX, stepY] to snap drag to a perfectly aligned grid.
Keyboard Movement
Focus + arrow keys to move with the keyboard (Shift for bigger steps).
Position Persistence
Set rememberLastPosition + storageKey to restore position across sessions.
Composes Cleanly
Nest Resizable inside Moveable to build floating, resizable panels.