Primitives

createSortable

Create sortable elements with the createSortable primitive.

Usage

The createSortable primitive combines draggable and droppable behavior with sorting logic. Import it from @dnd-kit/svelte/sortable.

Each sortable item must live in its own component (SortableItem.svelte above), with createSortable called in that component’s <script>. Calling createSortable inline in an {#each} block — for example via {@const sortable = createSortable(...)} — re-runs the call on every reorder, which creates a fresh Sortable instance per render and breaks sort transition animations. Wrapping each item in its own component is what gives createSortable a stable per-item identity across reorders.

Pass reactive values like id and index as getter properties (e.g. get id() { return id; }, get index() { return index; }) so the underlying sortable stays in sync as items are reordered. Visual sorting during drag is driven by calling move() in onDragOver; the onDragEnd handler only needs to restore the snapshot when the drag is canceled.

Without the move helper

The example above uses the move helper from @dnd-kit/helpers, a convenience function that takes your items and a drag event and returns a new array with the item moved to its new position. It supports flat arrays and grouped records, handles canceled drags, and works with multiple lists.

If you need more control over state updates, you can manage state manually using the isSortable type guard and the sortable properties (initialIndex, index).

Call move() in onDragOver for live visual sorting, and restore the snapshot in onDragEnd only when the drag is canceled:

<script>
  import {createSortable} from '@dnd-kit/svelte/sortable';

  let {id, index} = $props();

  const sortable = createSortable({
    get id() { return id; },
    get index() { return index; },
  });
</script>

<li {@attach sortable.attach}>
  Item {id}
</li>
<script>
  import {DragDropProvider} from '@dnd-kit/svelte';
  import {isSortable} from '@dnd-kit/svelte/sortable';
  import SortableItem from './SortableItem.svelte';

  let items = $state([1, 2, 3, 4]);
  let snapshot = [];

  function onDragStart() {
    snapshot = items.slice();
  }

  function onDragOver(event) {
    const {source, target} = event.operation;

    if (isSortable(source) && isSortable(target)) {
      const fromIndex = source.index;
      const toIndex = target.index;

      if (fromIndex !== toIndex) {
        const newItems = [...items];
        const [removed] = newItems.splice(fromIndex, 1);
        newItems.splice(toIndex, 0, removed);
        items = newItems;
      }
    }
  }

  function onDragEnd(event) {
    if (event.canceled) items = snapshot;
  }
</script>

<DragDropProvider {onDragStart} {onDragOver} {onDragEnd}>
  <ul>
    {#each items as id, index (id)}
      <SortableItem {id} {index} />
    {/each}
  </ul>
</DragDropProvider>

Learn more about type guards and manual state management in the Sortable concepts page.

Input

All input properties accept plain values or getter functions for reactivity.

id
UniqueIdentifier | (() => UniqueIdentifier)
required

A unique identifier for this sortable instance.

index
number | (() => number)
required

The current index of this item in the sorted list.

group
string | (() => string)

The group this sortable belongs to. Used for sorting across multiple lists.

accept
string | string[] | (() => string | string[])

The types of draggable elements this sortable accepts.

type
string | (() => string)

The type of this sortable element.

plugins
PluginDescriptor[] | (() => PluginDescriptor[])

An array of plugin descriptors for per-entity plugin configuration. Use Plugin.configure() to create descriptors. For example, Feedback.configure({ feedback: 'clone' }).

transition
SortableTransition | (() => SortableTransition)

Animation transition configuration for sort operations.

modifiers
Modifier[] | (() => Modifier[])

Modifiers to apply to this sortable instance.

sensors
Sensor[] | (() => Sensor[])

Sensors to use for this sortable instance.

collisionDetector
CollisionDetector | (() => CollisionDetector)

A custom collision detection algorithm.

collisionPriority
number | (() => number)

The collision priority of this sortable element. Higher values take precedence when multiple droppable elements overlap.

disabled
boolean | SortableDisabled | (() => boolean | SortableDisabled)

Whether the sortable is disabled. Pass an object to disable dragging and dropping independently:

interface SortableDisabled {
  draggable?: boolean; // Prevent this item from being dragged
  droppable?: boolean; // Prevent other items from being dropped on this one
}
data
Data | (() => Data)

Custom data to attach to this sortable instance.

Output

isDragging
boolean

Whether this element is currently being dragged.

isDropping
boolean

Whether this element is in the process of being dropped.

isDragSource
boolean

Whether this element is the source of the current drag operation.

isDropTarget
boolean

Whether this element is currently a drop target.

sortable
Sortable

The underlying Sortable instance.

attach
(element: HTMLElement) => () => void

Attachment function for the sortable element. Use with {@attach}.

attachHandle
(element: HTMLElement) => () => void

Attachment function for a drag handle. Use with {@attach}.

attachSource
(element: HTMLElement) => () => void

Attachment function for the drag source element (when different from the sortable element).

attachTarget
(element: HTMLElement) => () => void

Attachment function for the drop target element (when different from the sortable element).