Start here to see how framework-owned state becomes a sortable SnapSort tree. Each example includes a Svelte source tab. React and Vanilla applications use the same identities and mutation events with their own rendering APIs.

Basic Container

Place ordinary Svelte children inside Container. SnapSort does not own the collection loop or inspect its children. Each sortable Item needs a stable itemId, and each Svelte loop needs the corresponding stable key.

This first preview disables pointer interaction so the component structure is easy to inspect. Its source still includes the complete RenderTree callbacks.

A basic container

See the complete Container API.

Sortable Container

Store a RenderTree in $state.raw. In onItemMove, pass the event and the current tree to reduceRenderTree; the immutable helper returns the next application-owned keyed sequence, and Svelte renders it synchronously.

RenderTree contains engine-owned identity objects. $state.raw keeps those identities intact; publish the reducer’s returned root instead of mutating nested entries in place. Add and delete controls originating in the application edit this sequence directly rather than waiting for a SnapSort callback.

A sortable container

Svelte owns the rendered collection, so persistent callbacks such as onItemMove must update state synchronously. The adapter commits that render before SnapSort measures and animates the final DOM.

Basic Item

Render an Item from each ordinary entry in the application-owned keyed loop, give it entry.itemId, and put the entry’s content inside the component. When onItemMove updates the render tree or another application collection, Svelte reconciles the new order.

A basic item

Adding or deleting an ordinary application value is an application-state operation. When its keyed Item mounts or unmounts, the wrapper synchronizes the core registration; that reconciliation does not emit onItemInsert or onItemRemove. Those callbacks report core-originated commands instead.

See the complete Item API.

Items and Nested Containers

Rendering has three branches: a ghost renders Ghost, an ordinary entry with childTree renders a nested Container, and any other ordinary entry renders Item. A Container is already the sortable Item for its parent entry, so do not wrap it in another Item.

Ordinary markup inside an Item does not need a childTree. Set childTree only when the entry itself renders a SnapSort Container with a sortable sequence of its own. Give that Container the entry’s itemId; set locked={false} only when the whole Container should be movable.

The example remains one SnapSort tree. Its nested groups use application metadata and getDropPriority so their tasks can move between them while the parent rejects task drops into its top-level mixture.

Items and nested containers

See Nested Containers for locking, selection, and deeper composition.