dragula

A vanilla JavaScript drag-and-drop library that figures out sort order on its own, with no framework required.

Library
npm
v3.7.3
22,133stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
43/100Fair
Development Activity0
Maintenance0
Community72
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
61/100Good
Architecture68
Code Quality60
Innovation45
Learning Curve70

Dragula is a vanilla JavaScript library, created by Nicolas Bevacqua in 2015, that makes drag-and-drop between DOM containers close to a one-line integration: pass it a list of container elements and it wires up mouse/touch events, renders a floating mirror of the dragged item, and figures out the correct sort position by comparing the cursor against sibling bounding rectangles.

It ships with no required framework — options like moves, accepts, invalid, and copy give fine-grained control over what can be dragged and where it can land, and official Angular and React bridge packages exist for teams that want a component wrapper. The library has been effectively feature-complete and in low-maintenance mode since 2020 (last tagged release 3.7.3), but remains widely used and forms the vanilla-JS core behind several drag-and-drop wrapper libraries.

What You Get

  • A single dragula(containers, options) factory that returns an event-emitting drake API (start, end, cancel, remove, destroy, canMove).
  • Automatic mirror-element rendering and CSS classes (gu-mirror, gu-transit, gu-hide, gu-unselectable) to style drag feedback.
  • Ten drake events (drag, dragend, drop, cancel, remove, shadow, over, out, cloned) for hooking persistence or animation into any stage of a drag.
  • Prebuilt UMD, minified, and CSS builds in dist/ for use without a bundler, plus official Angular and React bridge packages.

Common Use Cases

  • Kanban/task-board column reordering.
  • Sortable admin list or table rows.
  • Drag-to-copy asset or file organizers.
  • Cross-container playlist or queue builders.

Under The Hood

Architecture Dragula centers on a single factory function, dragula(containers, options) (dragula.js), that returns a drake object built with the contra/emitter mixin — an event emitter rather than a class instance. All drag state (the dragged item, its source container, the floating mirror element, offsets, and the current/initial sibling) lives in closure-scoped variables rather than object fields, and every DOM listener (mousedown/mouseup/mousemove and their touch/pointer equivalents via the internal touchy helper) is delegated from document.documentElement instead of bound per draggable element. The tiny classes.js module is the only other file in the runtime bundle, providing a self-contained regex-based class add/remove helper for toggling gu-transit/gu-mirror/gu-hide/gu-unselectable. There’s no dependency injection or plugin registry; extension points are limited to the moves/accepts/invalid/copy option callbacks, so changing core drag-detection logic means editing the one large closure directly.

Tech Stack Written in plain ES5-style JavaScript with 'use strict' and no TypeScript, depending only on contra (event emitter) and crossvent (cross-browser event binding), both maintained by the same author. The build pipeline uses Browserify to produce a UMD bundle (dist/dragula.js), uglify-js for minification, Stylus to compile dragula.styl into dist/dragula.css, and jshint (not ESLint) for linting per .jshintrc. Tests run via tape bundled through Browserify and executed in a real browser via tape-run; watchify drives the dev rebuild loop. Distribution targets the browser directly — no server or database component — via npm and a CDN build for script-tag use.

Code Quality The test/ directory has focused suites for drag, drop, cancel, remove, destroy, containers, defaults, and the public API, each exercising drake events against a real DOM via tape-run, which is a reasonably thorough behavioral net for a UI interaction library. There are no type annotations or .d.ts files, and error handling is implicit — most internal functions guard with early returns (e.g., if (!drake.dragging) return;) rather than throwing, which fits a UI library where failures should silently no-op. Naming is terse and consistent (underscore-prefixed closure variables like _item, _mirror, _source), matching typical 2015-era vanilla-JS conventions, and linting is enforced via jshint rather than a modern linter. The repository has had no commits since mid-2024 and no recent CI activity.

API Design The public surface is deliberately minimal: call dragula(containers, options) and get back a drake with start/end/cancel/remove/destroy/canMove methods and ten emitted events (drag, dragend, drop, cancel, remove, shadow, over, out, cloned). Getting started requires no markup conventions or wrapper components — any DOM elements can be containers — and the four CSS classes needed for styling are documented directly in the README. Official Angular and React bridge packages exist for teams wanting idiomatic framework components instead of the raw vanilla API, lowering onboarding friction further for those ecosystems.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search