The JavaScript Drag & Drop library your grandparents warned you about.
npx @tessl/cli install tessl/npm-shopify--draggable@1.1.00
# Shopify Draggable
1
2
Shopify Draggable is a comprehensive JavaScript drag-and-drop library built with TypeScript that offers complete control over drag-and-drop behavior through a flexible API. It abstracts native browser events (drag, mouse, touch, and force touch) into a unified interface and includes specialized modules: Sortable for reordering elements, Droppable for defining drop zones, and Swappable for element swapping.
3
4
## Package Information
5
6
- **Package Name**: @shopify/draggable
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install @shopify/draggable`
10
11
## Core Imports
12
13
```typescript
14
import { Draggable, Sortable, Droppable, Swappable } from "@shopify/draggable";
15
```
16
17
Base classes and utilities:
18
19
```typescript
20
import { BaseEvent, BasePlugin, Sensors, Plugins } from "@shopify/draggable";
21
```
22
23
For CommonJS:
24
25
```javascript
26
const { Draggable, Sortable, Droppable, Swappable } = require("@shopify/draggable");
27
const { BaseEvent, BasePlugin, Sensors, Plugins } = require("@shopify/draggable");
28
```
29
30
ES modules (alternative imports):
31
32
```typescript
33
import Draggable from "@shopify/draggable/lib/draggable";
34
import Sortable from "@shopify/draggable/lib/sortable";
35
```
36
37
## Basic Usage
38
39
```typescript
40
import { Draggable } from "@shopify/draggable";
41
42
// Basic draggable setup
43
const draggable = new Draggable(document.querySelectorAll('.container'), {
44
draggable: '.item'
45
});
46
47
// Listen to drag events
48
draggable.on('drag:start', (event) => {
49
console.log('Started dragging:', event.source);
50
});
51
52
draggable.on('drag:stop', (event) => {
53
console.log('Stopped dragging:', event.source);
54
});
55
56
// Cleanup when done
57
draggable.destroy();
58
```
59
60
## Architecture
61
62
Shopify Draggable is built around several key components:
63
64
- **Core Draggable**: Base class providing fundamental drag-and-drop functionality
65
- **Specialized Classes**: Sortable, Droppable, and Swappable extend Draggable for specific use cases
66
- **Event System**: Comprehensive event lifecycle with cancelable events and custom data
67
- **Sensor System**: Pluggable input handling for mouse, touch, and native drag events
68
- **Plugin Architecture**: Extensible system with built-in plugins for mirrors, scrolling, announcements, etc.
69
- **Type Safety**: Full TypeScript integration with generic event types and comprehensive interfaces
70
71
## Capabilities
72
73
### Core Draggable
74
75
Basic drag-and-drop functionality with container management, event handling, and plugin system. Provides the foundation for all other draggable types.
76
77
```typescript { .api }
78
class Draggable<TEventListType = DraggableEventNames> {
79
constructor(containers: DraggableContainer, options?: DraggableOptions);
80
destroy(): void;
81
on<T extends TEventListType>(eventName: T, callback: (event: GetEventByEventName<T>) => void): this;
82
off<T extends TEventListType>(eventName: T, callback: (event: GetEventByEventName<T>) => void): this;
83
trigger(event: AbstractEvent): void;
84
isDragging(): boolean;
85
}
86
87
type DraggableContainer = HTMLElement | HTMLElement[] | NodeList;
88
```
89
90
[Core Draggable](./core-draggable.md)
91
92
### Sortable Lists
93
94
Reorder elements within or between containers with automatic position tracking and smooth animations. Perfect for to-do lists, priority queues, and dashboard widgets.
95
96
```typescript { .api }
97
class Sortable<T = SortableEventNames> extends Draggable<T> {
98
constructor(containers: DraggableContainer, options?: DraggableOptions);
99
index(element: HTMLElement): number;
100
getSortableElementsForContainer(container: HTMLElement): HTMLElement[];
101
}
102
```
103
104
[Sortable Lists](./sortable.md)
105
106
### Droppable Zones
107
108
Create designated drop zones where draggable elements can be placed. Includes visual feedback and validation for valid/invalid drop targets.
109
110
```typescript { .api }
111
class Droppable<T = DroppableEventNames> extends Draggable<T> {
112
constructor(containers: DraggableContainer, options: DroppableOptions);
113
getClassNameFor(name: DroppableClassNames): string;
114
}
115
116
interface DroppableOptions extends DraggableOptions {
117
dropzone: string | NodeList | HTMLElement[] | (() => NodeList | HTMLElement[]);
118
classes?: {[key in DroppableClassNames]: string};
119
}
120
```
121
122
[Droppable Zones](./droppable.md)
123
124
### Swappable Elements
125
126
Enable element swapping where dragging over another element exchanges their positions. Order-independent interaction for grid layouts and card arrangements.
127
128
```typescript { .api }
129
class Swappable<T = SwappableEventNames> extends Draggable<T> {
130
constructor(containers: DraggableContainer, options?: DraggableOptions);
131
}
132
```
133
134
[Swappable Elements](./swappable.md)
135
136
### Event System
137
138
Comprehensive event lifecycle with drag events, specialized events for each draggable type, and plugin-specific events. All events extend AbstractEvent with cancellation support.
139
140
```typescript { .api }
141
abstract class AbstractEvent<TData = {[key: string]: any}> {
142
readonly type: string;
143
readonly cancelable: boolean;
144
constructor(data: TData);
145
cancel(): void;
146
canceled(): boolean;
147
clone(data?: Partial<TData>): AbstractEvent<TData>;
148
}
149
150
export {AbstractEvent as BaseEvent};
151
```
152
153
[Events](./events.md)
154
155
### Sensors
156
157
Input detection system supporting mouse, touch, native drag events, and force touch. Pluggable architecture allows custom sensor implementation for specialized input handling.
158
159
```typescript { .api }
160
class Sensor {
161
constructor(containers: HTMLElement | HTMLElement[] | NodeList, options?: SensorOptions);
162
attach(): this;
163
detach(): this;
164
addContainer(...containers: HTMLElement[]): void;
165
removeContainer(...containers: HTMLElement[]): void;
166
trigger(element: HTMLElement, sensorEvent: SensorEvent): SensorEvent;
167
}
168
```
169
170
[Sensors](./sensors.md)
171
172
### Plugins
173
174
Extensible plugin system with built-in plugins for mirror elements, auto-scrolling, accessibility announcements, focus management, collision detection, and animations.
175
176
```typescript { .api }
177
abstract class AbstractPlugin {
178
constructor(draggable: Draggable);
179
protected abstract attach(): void;
180
protected abstract detach(): void;
181
}
182
183
export {AbstractPlugin as BasePlugin};
184
```
185
186
[Plugins](./plugins.md)
187
188
## Types
189
190
```typescript { .api }
191
interface DraggableOptions {
192
draggable?: string;
193
distance?: number;
194
handle?: string | NodeList | HTMLElement[] | HTMLElement | ((currentElement: HTMLElement) => HTMLElement);
195
delay?: number | DelayOptions;
196
placedTimeout?: number;
197
plugins?: (typeof AbstractPlugin)[];
198
sensors?: Sensor[];
199
exclude?: {
200
plugins?: (typeof AbstractPlugin)[];
201
sensors?: (typeof Sensor)[];
202
};
203
classes?: {[key in DraggableClassNames]: string | string[]};
204
announcements?: AnnouncementOptions;
205
collidables?: Collidables;
206
mirror?: MirrorOptions;
207
scrollable?: ScrollableOptions;
208
swapAnimation?: SwapAnimationOptions;
209
sortAnimation?: SortAnimationOptions;
210
}
211
212
interface DelayOptions {
213
mouse?: number;
214
drag?: number;
215
touch?: number;
216
}
217
218
type DraggableClassNames =
219
| 'body:dragging'
220
| 'container:dragging'
221
| 'source:dragging'
222
| 'source:placed'
223
| 'container:placed'
224
| 'draggable:over'
225
| 'container:over'
226
| 'source:original'
227
| 'mirror';
228
```