Code
<script lang="ts">
import { useSortable } from 'svelora';
let items = $state([
{ id: 1, label: 'Design' },
{ id: 2, label: 'Build' },
{ id: 3, label: 'Ship' }
]);
const sortable = useSortable({
getItems: () => items,
getId: (item) => item.id,
onReorder: (next) => (items = next),
handle: '[data-sortable-handle]'
});
</script>
<sortable.Provider>
<div use:sortable.container class="space-y-2">
{#each items as item, index (item.id)}
<div use:sortable.item={{ index, item }} class="flex items-center gap-2 rounded-lg border p-3">
<button type="button" data-sortable-handle aria-label="Drag">::</button>
{item.label}
</div>
{/each}
</div>
</sortable.Provider>
useSortable
Sortable list reordering powered by @dnd-kit/svelte.
Wrap markup in sortable.Provider,
attach use:sortable.item to each row, and optionally use use:sortable.container on the list wrapper. Browse all demos in the Drag & Drop playground.
When to use what
useSortable / SortableList
Reorder items inside one list (tasks, menu items, table rows).
Move items between containers (kanban columns, trays).
Drag files from the OS onto a dropzone — not for reordering UI lists.
Reorder rich-text blocks inside TipTap — built into Editor, not this hook.
Manual markup
Horizontal axis
SortableList component
Prefer a styled wrapper? See SortableList.
API Reference
useSortable options
getItems
() => T[]
Reactive getter for the current array.
getId
(item: T) => string | number
Stable id per row (must match data-sortable-id).
onReorder
(items: T[]) => void
Called with the reordered array after drop.
axis
'vertical' | 'horizontal' | 'grid' | (() => ...)
Drag axis. Default: vertical. Use grid for CSS grid layouts.
handle
string | (() => string | undefined)
Handle selector. Omit to drag the whole row.
disabled
boolean | (() => boolean)
Disable sorting. Default: false.
Return value
Provider
Component
Required wrapper — mounts @dnd-kit/svelte DragDropProvider. Accepts an optional `overlay` snippet for custom drag overlays.
container
Action<HTMLElement>
Optional list wrapper — sets data-sortable-active while dragging.
item
Action<HTMLElement, { index, item }>
Attach to each row with the current index and item.
draggingId
string | number | null
Readonly id of the row currently being dragged.
Markup attributes
use:sortable.item
Required on each row — pass { index, item } from the #each block.
data-sortable-handle
Optional handle element when using handle selector.
data-sortable-item / data-sortable-id
Set automatically by use:sortable.item for styling hooks.