Lightweight, high-performance drag and drop grid library with smooth animations and touch support. Create interactive, swappable grids with minimal overhead and maximum responsiveness.
npm install swappableSwappable is a lightweight and performant JavaScript library for creating
interactive, draggable, and swappable grid layouts. Built with modern web APIs,
it offers smooth animations and a simple API for common use cases.
- Touch-first Draggable Items: Seamless drag-and-drop functionality on both
desktop and mobile devices.
- Smooth Animations: Utilizes the FLIP (First, Last, Invert, Play) animation
technique for fluid layout transitions after a swap or item change.
- CSS-driven Layout: Leverages CSS Grid for a flexible and responsive
layout.
- Lightweight & Performant: No external dependencies, ensuring a small
footprint.
- Customizable: Easily configure class names, animation durations, and drag
behavior.\
codepen\
demo
``bash`
$ npm i swappable
`js`
import Swappable from "swappable";
import "./node_modules/swappable/dist/swappable.css";
Create a container with grid items and initialize Swappable:
`html
Item 1
Item 2
Item 3
Item 4
`
Customize Swappable with the following options:
| Option | Type | Default | Description |
| ---------------- | ---------------- | -------------- | ------------------------------------------------ |
| dragEnabled | boolean | true | Enable or disable dragging. |dragHandle
| | string \| null | ".grid-item" | Selector for drag handle (null for entire item). |classNames
| | ClassNames | See below | Custom class names for grid items and states. |layoutDuration
| | number | 300 | Duration of layout animations (ms). |swapDuration
| | number | 300 | Duration of swap animations (ms). |layoutEasing
| | string | "ease" | Easing function for animations. |itemsPerRow
| | number | 4 | Number of items per row in the grid. |longPressDelay
| | number | 100 | Delay (ms) for initiating drag on touch devices. |
Default classNames:
`json`
{
"item": "grid-item",
"drag": "dragging",
"placeholder": "placeholder",
"ghost": "ghost",
"hidden": "hidden"
}
Swappable supports the following events:
| Event | Data Type | Description |
| ------------- | ------------------------------------------------------------------------------------------ | ------------------------------------- |
| add | { items: HTMLElement[] } | Fired when items are added. |remove
| | { items: HTMLElement[] } | Fired when items are removed. |dragStart
| | { item: HTMLElement, event: PointerEvent } | Fired when dragging starts. |dragMove
| | { item: HTMLElement, event: PointerEvent } | Fired during dragging. |swap
| | { fromIndex: number, toIndex: number, fromElement: HTMLElement, toElement: HTMLElement } | Fired when items are swapped. |sort
| | { oldIndex: number, newIndex: number, items: SwappableItemData[] } | Fired after sorting items. |dragEnd
| | { item: HTMLElement, event: PointerEvent } | Fired when dragging ends. |layoutStart
| | void | Fired before layout animation starts. |layoutEnd
| | void | Fired after layout animation ends. |
Example of event handling:
`javascript
grid.on("dragStart", ({ item, event }) => {
console.log("Dragging started on", item);
});
grid.on("swap", ({ fromIndex, toIndex }) => {
console.log(Swapped item from ${fromIndex} to ${toIndex});`
});
| Method | Parameters | Description |
| --------- | ---------------------------------------- | ----------------------------------- |
| on | event: keyof SwappableEvents, callback | Attach an event listener. |off
| | event: keyof SwappableEvents | Remove an event listener. |layout
| | duration?: number | Recompute and animate layout. |add
| | element: HTMLElement, index?: number | Add a new item to the grid. |remove
| | target: HTMLElement \| number | Remove an item by element or index. |select
| | target: HTMLElement \| number | Select an item by element or index. |swap
| | fromIndex: number, toIndex: number | Swap two items by index. |refresh
| | None | Refresh the grid layout. |destroy
| | None | Destroy the instance and clean up. |detach
| | None | Detach event listeners. |enable
| | None | Enable dragging. |disable
| | None | Disable dragging. |
A complete example with a 4x2 grid and event logging:
`html
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/swappable/dist/swappable.css"
>
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6
Item 7
Item 8
`
---
`js
import Swappable, { withAutoResponsiveLayout, withHistory } from "swappable";
let swappableInstance = new Swappable("#my-grid");
// with the history plugin
let swappableWithHistory = withHistory(swappableInstance, {
maxHistorySize: 20,
});
// with the responsive layout plugin
let finalSwappable = withAutoResponsiveLayout(swappableWithHistory, {
breakpoints: [
{ breakpoint: 0, items: 1 }, // 1 column for smallest screens
{ breakpoint: 576, items: 2 }, // 2 columns for screens >= 576px
{ breakpoint: 768, items: 3 }, // 3 columns for screens >= 768px
{ breakpoint: 992, items: 4 }, // 4 columns for screens >= 992px
],
});
``
We welcome contributions\! Feel free to open issues or pull requests on the
GitHub repository.
---
This project is licensed under the MIT License.