or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-draggable.mddroppable.mdevents.mdindex.mdplugins.mdsensors.mdsortable.mdswappable.md
tile.json

tessl/npm-shopify--draggable

The JavaScript Drag & Drop library your grandparents warned you about.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@shopify/draggable@1.1.x

To install, run

npx @tessl/cli install tessl/npm-shopify--draggable@1.1.0

index.mddocs/

Shopify Draggable

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.

Package Information

  • Package Name: @shopify/draggable
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @shopify/draggable

Core Imports

import { Draggable, Sortable, Droppable, Swappable } from "@shopify/draggable";

Base classes and utilities:

import { BaseEvent, BasePlugin, Sensors, Plugins } from "@shopify/draggable";

For CommonJS:

const { Draggable, Sortable, Droppable, Swappable } = require("@shopify/draggable");
const { BaseEvent, BasePlugin, Sensors, Plugins } = require("@shopify/draggable");

ES modules (alternative imports):

import Draggable from "@shopify/draggable/lib/draggable";
import Sortable from "@shopify/draggable/lib/sortable";

Basic Usage

import { Draggable } from "@shopify/draggable";

// Basic draggable setup
const draggable = new Draggable(document.querySelectorAll('.container'), {
  draggable: '.item'
});

// Listen to drag events
draggable.on('drag:start', (event) => {
  console.log('Started dragging:', event.source);
});

draggable.on('drag:stop', (event) => {
  console.log('Stopped dragging:', event.source);
});

// Cleanup when done
draggable.destroy();

Architecture

Shopify Draggable is built around several key components:

  • Core Draggable: Base class providing fundamental drag-and-drop functionality
  • Specialized Classes: Sortable, Droppable, and Swappable extend Draggable for specific use cases
  • Event System: Comprehensive event lifecycle with cancelable events and custom data
  • Sensor System: Pluggable input handling for mouse, touch, and native drag events
  • Plugin Architecture: Extensible system with built-in plugins for mirrors, scrolling, announcements, etc.
  • Type Safety: Full TypeScript integration with generic event types and comprehensive interfaces

Capabilities

Core Draggable

Basic drag-and-drop functionality with container management, event handling, and plugin system. Provides the foundation for all other draggable types.

class Draggable<TEventListType = DraggableEventNames> {
  constructor(containers: DraggableContainer, options?: DraggableOptions);
  destroy(): void;
  on<T extends TEventListType>(eventName: T, callback: (event: GetEventByEventName<T>) => void): this;
  off<T extends TEventListType>(eventName: T, callback: (event: GetEventByEventName<T>) => void): this;
  trigger(event: AbstractEvent): void;
  isDragging(): boolean;
}

type DraggableContainer = HTMLElement | HTMLElement[] | NodeList;

Core Draggable

Sortable Lists

Reorder elements within or between containers with automatic position tracking and smooth animations. Perfect for to-do lists, priority queues, and dashboard widgets.

class Sortable<T = SortableEventNames> extends Draggable<T> {
  constructor(containers: DraggableContainer, options?: DraggableOptions);
  index(element: HTMLElement): number;
  getSortableElementsForContainer(container: HTMLElement): HTMLElement[];
}

Sortable Lists

Droppable Zones

Create designated drop zones where draggable elements can be placed. Includes visual feedback and validation for valid/invalid drop targets.

class Droppable<T = DroppableEventNames> extends Draggable<T> {
  constructor(containers: DraggableContainer, options: DroppableOptions);
  getClassNameFor(name: DroppableClassNames): string;
}

interface DroppableOptions extends DraggableOptions {
  dropzone: string | NodeList | HTMLElement[] | (() => NodeList | HTMLElement[]);
  classes?: {[key in DroppableClassNames]: string};
}

Droppable Zones

Swappable Elements

Enable element swapping where dragging over another element exchanges their positions. Order-independent interaction for grid layouts and card arrangements.

class Swappable<T = SwappableEventNames> extends Draggable<T> {
  constructor(containers: DraggableContainer, options?: DraggableOptions);
}

Swappable Elements

Event System

Comprehensive event lifecycle with drag events, specialized events for each draggable type, and plugin-specific events. All events extend AbstractEvent with cancellation support.

abstract class AbstractEvent<TData = {[key: string]: any}> {
  readonly type: string;
  readonly cancelable: boolean;
  constructor(data: TData);
  cancel(): void;
  canceled(): boolean;
  clone(data?: Partial<TData>): AbstractEvent<TData>;
}

export {AbstractEvent as BaseEvent};

Events

Sensors

Input detection system supporting mouse, touch, native drag events, and force touch. Pluggable architecture allows custom sensor implementation for specialized input handling.

class Sensor {
  constructor(containers: HTMLElement | HTMLElement[] | NodeList, options?: SensorOptions);
  attach(): this;
  detach(): this;
  addContainer(...containers: HTMLElement[]): void;
  removeContainer(...containers: HTMLElement[]): void;
  trigger(element: HTMLElement, sensorEvent: SensorEvent): SensorEvent;
}

Sensors

Plugins

Extensible plugin system with built-in plugins for mirror elements, auto-scrolling, accessibility announcements, focus management, collision detection, and animations.

abstract class AbstractPlugin {
  constructor(draggable: Draggable);
  protected abstract attach(): void;
  protected abstract detach(): void;
}

export {AbstractPlugin as BasePlugin};

Plugins

Types

interface DraggableOptions {
  draggable?: string;
  distance?: number;
  handle?: string | NodeList | HTMLElement[] | HTMLElement | ((currentElement: HTMLElement) => HTMLElement);
  delay?: number | DelayOptions;
  placedTimeout?: number;
  plugins?: (typeof AbstractPlugin)[];
  sensors?: Sensor[];
  exclude?: {
    plugins?: (typeof AbstractPlugin)[];
    sensors?: (typeof Sensor)[];
  };
  classes?: {[key in DraggableClassNames]: string | string[]};
  announcements?: AnnouncementOptions;
  collidables?: Collidables;
  mirror?: MirrorOptions;
  scrollable?: ScrollableOptions;
  swapAnimation?: SwapAnimationOptions;
  sortAnimation?: SortAnimationOptions;
}

interface DelayOptions {
  mouse?: number;
  drag?: number;
  touch?: number;
}

type DraggableClassNames =
  | 'body:dragging'
  | 'container:dragging'
  | 'source:dragging'
  | 'source:placed'
  | 'container:placed'
  | 'draggable:over'
  | 'container:over'
  | 'source:original'
  | 'mirror';