@horuse/svelte-dnd
v1.0.0
Published
A drag-and-drop library for Svelte 5 with animated drop previews, auto-scroll, pointer & touch support, and multi-container support.
Downloads
998
Maintainers
Readme
@horuse/svelte-dnd
A drag-and-drop library for Svelte 5 with animated drop previews, auto-scroll, and multi-container support.

Features
- Vertical, horizontal, and grid layouts
- Pointer, touch, and keyboard sensors built-in (WAI-ARIA accessible)
- Animated drop previews rendered automatically
- Auto-scroll when dragging near container edges
- Move items between multiple containers (kanban-style)
- Custom ghost element via Svelte snippets
- Zero dependencies beyond Svelte 5
Installation
npm install @horuse/svelte-dndBasic Example
A minimal working drag-and-drop setup requires three components: DndProvider, DndDroppable, and DndDraggable. Drop previews are rendered automatically — no manual placement needed.
<script lang="ts">
import {
DndProvider,
DndDroppable,
DndDraggable,
DndController,
sortable
} from '@horuse/svelte-dnd'
let items = $state([
{ id: '1', label: 'First item' },
{ id: '2', label: 'Second item' },
{ id: '3', label: 'Third item' }
])
const controller = new DndController()
controller.onDrop(({ item, target }) => {
const fromIndex = items.findIndex((i) => i.id === item.id)
if (fromIndex === -1) return
const updated = [...items]
const [moved] = updated.splice(fromIndex, 1)
updated.splice(target.position, 0, moved)
items = updated
})
</script>
<DndProvider {controller}>
<DndDroppable id="list" strategy={sortable()}>
{#each items as item, index (item.id)}
<DndDraggable id={item.id} position={index}>
{item.label}
</DndDraggable>
{/each}
</DndDroppable>
</DndProvider>How It Works
- DndProvider wraps your app and provides the
DndControllercontext to all child components. - DndDroppable defines a container where items can be dropped. Pass a
strategy—sortable()(default vertical),sortable({ layout: 'horizontal' }),sortable({ layout: 'grid' }), ortarget()for a single drop zone with no previews. - DndDraggable wraps each draggable item. Each must have a unique
idand apositionmatching its index in the list. - The dragged item is hidden automatically — the
.dnd-draggable--draggingclass setsopacity: 0so only the ghost follows the cursor. No manual filtering needed. - Use
controller.onDrop()to handle reordering logic when an item is dropped.
Documentation
Full docs and live examples are available at the documentation site.
