or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

draggable-core.mddraggable.mdindex.md

draggable.mddocs/

0

# Draggable Component

1

2

The Draggable component is a stateful React component that wraps an existing element and makes it draggable using CSS transforms. It manages its own position state and provides extensive configuration options for controlling drag behavior, boundaries, and styling.

3

4

## Capabilities

5

6

### Core Component

7

8

The main Draggable component that handles position management internally.

9

10

```typescript { .api }

11

/**

12

* A React component that makes its single child element draggable

13

* @param props - Draggable configuration properties

14

*/

15

function Draggable(props: DraggableProps): React.ReactElement;

16

17

interface DraggableProps extends DraggableCoreProps {

18

// Movement constraints

19

axis?: 'both' | 'x' | 'y' | 'none';

20

bounds?: DraggableBounds | string | false;

21

22

// Position management

23

defaultPosition?: ControlPosition;

24

position?: ControlPosition;

25

positionOffset?: PositionOffsetControlPosition;

26

27

// Styling classes

28

defaultClassName?: string;

29

defaultClassNameDragging?: string;

30

defaultClassNameDragged?: string;

31

}

32

```

33

34

**Usage Examples:**

35

36

```javascript

37

import React from 'react';

38

import Draggable from 'react-draggable';

39

40

// Basic draggable element

41

function BasicDraggable() {

42

return (

43

<Draggable>

44

<div className="box">Basic draggable</div>

45

</Draggable>

46

);

47

}

48

49

// Draggable with axis constraint

50

function AxisConstrainedDraggable() {

51

return (

52

<Draggable axis="x">

53

<div className="slider">Horizontal only</div>

54

</Draggable>

55

);

56

}

57

58

// Controlled draggable

59

function ControlledDraggable() {

60

const [position, setPosition] = React.useState({ x: 0, y: 0 });

61

62

const handleDrag = (e, data) => {

63

setPosition({ x: data.x, y: data.y });

64

};

65

66

return (

67

<Draggable position={position} onDrag={handleDrag}>

68

<div>Position: {position.x}, {position.y}</div>

69

</Draggable>

70

);

71

}

72

```

73

74

### Position Management

75

76

Control element positioning with various options for initial position, controlled positioning, and position offsets.

77

78

```typescript { .api }

79

/**

80

* Initial position for uncontrolled draggable elements

81

*/

82

defaultPosition?: ControlPosition;

83

84

/**

85

* Controlled position - makes the component controlled

86

* When provided, component position is externally managed

87

*/

88

position?: ControlPosition;

89

90

/**

91

* Position offset from the element's natural position

92

* Supports pixel values or percentage strings

93

*/

94

positionOffset?: PositionOffsetControlPosition;

95

96

interface ControlPosition {

97

x: number;

98

y: number;

99

}

100

101

interface PositionOffsetControlPosition {

102

x: number | string;

103

y: number | string;

104

}

105

```

106

107

**Usage Examples:**

108

109

```javascript

110

import React, { useState } from 'react';

111

import Draggable from 'react-draggable';

112

113

// Uncontrolled with initial position

114

<Draggable defaultPosition={{ x: 100, y: 50 }}>

115

<div>Starts at (100, 50)</div>

116

</Draggable>

117

118

// Controlled positioning

119

function ControlledExample() {

120

const [pos, setPos] = useState({ x: 0, y: 0 });

121

122

return (

123

<Draggable

124

position={pos}

125

onDrag={(e, data) => setPos({ x: data.x, y: data.y })}

126

>

127

<div>Controlled position</div>

128

</Draggable>

129

);

130

}

131

132

// Position offset with percentages

133

<Draggable positionOffset={{ x: '50%', y: 20 }}>

134

<div>Offset from natural position</div>

135

</Draggable>

136

```

137

138

### Movement Constraints

139

140

Control which axes the element can move along and define movement boundaries.

141

142

```typescript { .api }

143

/**

144

* Constrains movement to specific axes

145

* 'both' - move freely (default)

146

* 'x' - horizontal movement only

147

* 'y' - vertical movement only

148

* 'none' - no movement (useful for touch scrolling)

149

*/

150

axis?: 'both' | 'x' | 'y' | 'none';

151

152

/**

153

* Boundaries for draggable movement

154

* Object - pixel boundaries: { left?: number, top?: number, right?: number, bottom?: number }

155

* 'parent' - restricted to offsetParent element

156

* CSS selector string - restricted to first matching element

157

* false - no boundaries (default)

158

*/

159

bounds?: DraggableBounds | string | false;

160

161

interface DraggableBounds {

162

left?: number;

163

right?: number;

164

top?: number;

165

bottom?: number;

166

}

167

```

168

169

**Usage Examples:**

170

171

```javascript

172

// Vertical slider

173

<Draggable axis="y" bounds={{ top: 0, bottom: 300 }}>

174

<div className="vertical-slider">Vertical only</div>

175

</Draggable>

176

177

// Bounded to parent element

178

<div className="container">

179

<Draggable bounds="parent">

180

<div>Can't leave parent</div>

181

</Draggable>

182

</div>

183

184

// Custom boundary selector

185

<Draggable bounds=".drag-area">

186

<div>Bounded to .drag-area element</div>

187

</Draggable>

188

189

// Pixel boundaries

190

<Draggable bounds={{ left: 0, top: 0, right: 500, bottom: 300 }}>

191

<div>Bounded to specific area</div>

192

</Draggable>

193

```

194

195

### Grid Snapping and Scaling

196

197

Snap movement to grid positions and scale drag calculations for zoomed interfaces.

198

199

```typescript { .api }

200

/**

201

* Snap dragging to a grid

202

* [x, y] - grid cell size in pixels for each axis

203

*/

204

grid?: [number, number];

205

206

/**

207

* Scale factor for drag distance calculations

208

* Useful when the draggable is inside a scaled/zoomed container

209

*/

210

scale?: number;

211

```

212

213

**Usage Examples:**

214

215

```javascript

216

// Snap to 20px grid

217

<Draggable grid={[20, 20]}>

218

<div>Snaps to grid</div>

219

</Draggable>

220

221

// Scale for zoomed interface (50% zoom)

222

<Draggable scale={0.5}>

223

<div>Scaled drag calculations</div>

224

</Draggable>

225

```

226

227

### Interaction Controls

228

229

Configure drag handles, cancel zones, and interaction behavior.

230

231

```typescript { .api }

232

/**

233

* CSS selector for drag handle

234

* Only elements matching this selector can initiate drag

235

*/

236

handle?: string;

237

238

/**

239

* CSS selector for cancel zones

240

* Elements matching this selector will not trigger drag

241

*/

242

cancel?: string;

243

244

/**

245

* Disable all dragging functionality

246

*/

247

disabled?: boolean;

248

249

/**

250

* Allow dragging with any mouse button (not just left-click)

251

*/

252

allowAnyClick?: boolean;

253

254

/**

255

* Allow normal scrolling on mobile touch devices

256

* Prevents drag on scroll gestures

257

*/

258

allowMobileScroll?: boolean;

259

```

260

261

**Usage Examples:**

262

263

```javascript

264

// Drag handle - only the .handle element starts drag

265

<Draggable handle=".handle">

266

<div>

267

<div className="handle">Drag me</div>

268

<div>Content area - not draggable</div>

269

</div>

270

</Draggable>

271

272

// Cancel zones - .no-drag elements prevent drag

273

<Draggable cancel=".no-drag">

274

<div>

275

<button className="no-drag">Button (not draggable)</button>

276

<div>Draggable area</div>

277

</div>

278

</Draggable>

279

280

// Mobile-friendly with scroll

281

<Draggable allowMobileScroll>

282

<div>Touch and drag, or scroll normally</div>

283

</Draggable>

284

```

285

286

### Event Handlers

287

288

Handle drag lifecycle events with detailed position and delta information.

289

290

```typescript { .api }

291

/**

292

* Called when dragging starts

293

* Return false to cancel the drag

294

*/

295

onStart?: DraggableEventHandler;

296

297

/**

298

* Called continuously during drag

299

* Return false to stop the drag

300

*/

301

onDrag?: DraggableEventHandler;

302

303

/**

304

* Called when dragging stops

305

*/

306

onStop?: DraggableEventHandler;

307

308

/**

309

* Called on mouse down events (before drag start)

310

*/

311

onMouseDown?: (e: MouseEvent) => void;

312

313

type DraggableEventHandler = (

314

e: DraggableEvent,

315

data: DraggableData

316

) => void | false;

317

318

interface DraggableData {

319

node: HTMLElement; // The dragged DOM element

320

x: number; // Current x position

321

y: number; // Current y position

322

deltaX: number; // Change in x since last event

323

deltaY: number; // Change in y since last event

324

lastX: number; // Previous x position

325

lastY: number; // Previous y position

326

}

327

```

328

329

**Usage Examples:**

330

331

```javascript

332

function EventHandlingDraggable() {

333

const handleStart = (e, data) => {

334

console.log('Drag started at:', data.x, data.y);

335

// Return false to cancel drag

336

if (data.x < 0) return false;

337

};

338

339

const handleDrag = (e, data) => {

340

console.log('Dragging:', {

341

position: [data.x, data.y],

342

delta: [data.deltaX, data.deltaY]

343

});

344

};

345

346

const handleStop = (e, data) => {

347

console.log('Drag stopped at:', data.x, data.y);

348

};

349

350

return (

351

<Draggable

352

onStart={handleStart}

353

onDrag={handleDrag}

354

onStop={handleStop}

355

>

356

<div>Event handling draggable</div>

357

</Draggable>

358

);

359

}

360

```

361

362

### Styling Classes

363

364

Customize CSS classes applied during different drag states.

365

366

```typescript { .api }

367

/**

368

* Base CSS class applied to the draggable element

369

* Default: 'react-draggable'

370

*/

371

defaultClassName?: string;

372

373

/**

374

* CSS class applied while dragging

375

* Default: 'react-draggable-dragging'

376

*/

377

defaultClassNameDragging?: string;

378

379

/**

380

* CSS class applied after element has been dragged

381

* Default: 'react-draggable-dragged'

382

*/

383

defaultClassNameDragged?: string;

384

```

385

386

**Usage Examples:**

387

388

```javascript

389

<Draggable

390

defaultClassName="my-draggable"

391

defaultClassNameDragging="my-draggable--dragging"

392

defaultClassNameDragged="my-draggable--dragged"

393

>

394

<div>Custom styled draggable</div>

395

</Draggable>

396

```

397

398

### Advanced Options

399

400

Advanced configuration for specific use cases and React compatibility.

401

402

```typescript { .api }

403

/**

404

* Automatically add user-select: none styles during drag

405

* Prevents text selection while dragging

406

*/

407

enableUserSelectHack?: boolean;

408

409

/**

410

* Custom offset parent for position calculations

411

* Used for calculating relative positions

412

*/

413

offsetParent?: HTMLElement;

414

415

/**

416

* React ref for the draggable element

417

* Recommended for React Strict Mode compatibility (avoids findDOMNode)

418

*/

419

nodeRef?: React.RefObject<HTMLElement>;

420

```

421

422

**Usage Examples:**

423

424

```javascript

425

import React, { useRef } from 'react';

426

import Draggable from 'react-draggable';

427

428

function AdvancedDraggable() {

429

const nodeRef = useRef(null);

430

431

return (

432

<Draggable

433

nodeRef={nodeRef}

434

enableUserSelectHack={false} // Allow text selection during drag

435

>

436

<div ref={nodeRef}>

437

Advanced draggable with ref

438

</div>

439

</Draggable>

440

);

441

}

442

```