React components for adding drag-and-drop functionality to React applications with position management and boundary controls
npx @tessl/cli install tessl/npm-react-draggable@4.5.0React Draggable is a React component library that provides drag-and-drop functionality for React applications. It offers two main components: Draggable (a stateful wrapper that manages position) and DraggableCore (a stateless component for full control over drag behavior). The library supports advanced features including axis constraints, boundary restrictions, grid snapping, custom handles, touch support, and CSS transform-based positioning for optimal performance.
npm install react-draggable// Default import (Draggable component)
import Draggable from 'react-draggable';
// Named import (DraggableCore component)
import { DraggableCore } from 'react-draggable';
// Both components together
import Draggable, { DraggableCore } from 'react-draggable';CommonJS:
// Default require
const Draggable = require('react-draggable');
const DraggableCore = Draggable.DraggableCore;
// Destructured require
const { default: Draggable, DraggableCore } = require('react-draggable');import React from 'react';
import Draggable from 'react-draggable';
function App() {
return (
<Draggable>
<div style={{ padding: '20px', background: '#f0f0f0' }}>
Drag me around!
</div>
</Draggable>
);
}
// With event handlers and position control
function ControlledDraggable() {
const [position, setPosition] = React.useState({ x: 0, y: 0 });
const handleDrag = (e, data) => {
setPosition({ x: data.x, y: data.y });
};
return (
<Draggable position={position} onDrag={handleDrag}>
<div>Controlled draggable element</div>
</Draggable>
);
}React Draggable is built around several key concepts:
interface ControlPosition {
x: number;
y: number;
}
interface PositionOffsetControlPosition {
x: number | string;
y: number | string;
}
interface DraggableData {
node: HTMLElement;
x: number;
y: number;
deltaX: number;
deltaY: number;
lastX: number;
lastY: number;
}
interface DraggableBounds {
left?: number;
right?: number;
top?: number;
bottom?: number;
}
type DraggableEvent = React.MouseEvent<HTMLElement | SVGElement>
| React.TouchEvent<HTMLElement | SVGElement>
| MouseEvent
| TouchEvent;
type DraggableEventHandler = (
e: DraggableEvent,
data: DraggableData
) => void | false;The main Draggable component provides a stateful draggable wrapper that manages its own position and applies CSS transforms to move elements smoothly.
interface DraggableProps {
// Position management
axis?: 'both' | 'x' | 'y' | 'none'; // default: 'both'
defaultPosition?: ControlPosition; // default: {x: 0, y: 0}
position?: ControlPosition;
positionOffset?: PositionOffsetControlPosition;
// Boundaries and constraints
bounds?: DraggableBounds | string | false; // default: false
grid?: [number, number];
scale?: number; // default: 1
// Interaction controls
handle?: string;
cancel?: string;
disabled?: boolean; // default: false
// Event handlers
onStart?: DraggableEventHandler; // default: () => {}
onDrag?: DraggableEventHandler; // default: () => {}
onStop?: DraggableEventHandler; // default: () => {}
onMouseDown?: (e: MouseEvent) => void; // default: () => {}
// Styling
defaultClassName?: string; // default: 'react-draggable'
defaultClassNameDragging?: string; // default: 'react-draggable-dragging'
defaultClassNameDragged?: string; // default: 'react-draggable-dragged'
// Advanced options
allowAnyClick?: boolean; // default: false
allowMobileScroll?: boolean; // default: false
enableUserSelectHack?: boolean; // default: true
offsetParent?: HTMLElement;
nodeRef?: React.RefObject<HTMLElement>;
// Required
children: React.ReactNode;
}The low-level DraggableCore component provides drag events without position management, giving full control over drag behavior and positioning to the parent component.
interface DraggableCoreProps {
// Interaction controls
handle?: string;
cancel?: string;
disabled?: boolean; // default: false
// Event handlers
onStart?: DraggableEventHandler; // default: () => {}
onDrag?: DraggableEventHandler; // default: () => {}
onStop?: DraggableEventHandler; // default: () => {}
onMouseDown?: (e: MouseEvent) => void; // default: () => {}
// Advanced options
allowAnyClick?: boolean; // default: false
allowMobileScroll?: boolean; // default: false
enableUserSelectHack?: boolean; // default: true
offsetParent?: HTMLElement;
grid?: [number, number];
scale?: number; // default: 1
nodeRef?: React.RefObject<HTMLElement>;
// Required
children: React.ReactNode;
}