v1.0
Registry / Page 03·03

Sortable list

Reorder custom rows with handles, keyboard controls, and order callbacks.

Compose SortableList.Root, Item, and Grabber. You own each row’s content: labels, badges, checkboxes, and menus can live alongside the handle.

Preview

Svelte Example.svelte
Press Enter to grab or resize widgets. Once grabbed, use Arrow keys to move/resize the widget, Enter to confirm the action, or Esc to cancel it.

Research

Review customer feedback

Prototype

Explore the interaction

Release

Prepare the changelog

Order: research, prototype, release

Installation

Start with a Tailwind project configured for shadcn and its theme variables. This copies editable source into your components directory; it does not install a second theme.

npx shadcn-svelte@latest add https://flexiboards.dev/r/svelte/flexi-sortable-list.json

API

PartProps and defaults
RootAll FlexiSortable props, plus onreorder(ids). Vertical by default, with gap-2.
ItemAll FlexiWidget props, plus a required, unique string id. It is stored in metadata.id for order reporting.
GrabberGrabber props, including an accessible label.

Use keyed each blocks alongside the item id. The item’s id wins over a conflicting metadata.id.

Reading the order

The board owns the displayed layout; children declare the items, not a controlled order. The callback reports IDs in layout order after a layout change (including drops, deletion, and programmatic moves), not initial creation or layout import. Store the returned order in your application, or persist the full layout with config.onLayoutChange. Both callbacks run when provided.

A custom target key (key) is respected by the callback. For multiple lists that exchange items, use Board instead of nesting separate roots.

Customization

Use class on Root for spacing and on Item for the row surface. Set direction="horizontal" for a horizontal list. Underlying sizing and behavior options remain available through config, targetConfig, and individual widget props.

A handle keeps dragging away from the rest of the row. Place interactive controls beside the handle, not inside it. Resizing is off by default, as rows normally size to their content.

Existing convenience API

The original default export from sortable-list.svelte is retained.

It still accepts items: { id, label }[] and the reorder callback; new compositions should use the namespace API above.

Motion

Movement uses short CSS transitions by default and respects reduced motion. Compare presets or disable transitions.