Data Display

SortableList

Keyboard-and-pointer reorderable list that emits onReorder when the user drags or arrow-keys an item into a new position with announcer feedback.

import { SortableList } from '@lostgradient/cinder/sortable-list';
data-displayreorder
01

Overview

Drag-and-drop reorderable list that emits the new order on each change.

Usage

svelte
<script lang="ts">
  import SortableList from '@lostgradient/cinder/sortable-list';

  let items = $state([
    { id: '1', label: 'First item' },
    { id: '2', label: 'Second item' },
    { id: '3', label: 'Third item' },
  ]);
</script>

<SortableList
  {items}
  getKey={(item) => item.id}
  getItemLabel={(item) => item.label}
  onReorder={(reordered) => {
    items = reordered;
  }}
>
  {#snippet row({ item })}
    <span>{item.label}</span>
  {/snippet}
</SortableList>
Live preview
02

When to use

Use when
  • Letting users manually reorder a small to medium list of items via drag handle or keyboard.
  • Surfacing live region announcements during a reorder for accessible feedback.
Avoid when
  • Showing a read-only list with no reorder affordance — use grid-list instead.
  • Sorting by a column or computed key — sort the source array and rerender.
03

Examples

Basic sortable list

Keyboard and pointer reorderable list with announcer feedback.

04

Props

Props for sortable-list
Name Type Default Required Bindable Description
items Item[] req The list of items to render.
getKey (item: Item) => stringnumber req Returns a stable key for each item. Must not change across reorders.
getItemLabel (item: Item, originalIndex: number) => string req Returns an accessible label for each item (e.g., "Buy milk"). The second argument is the item's original index in the items array (not its current visual position during a drag). Used in handle aria-label and announcements.
formatHandleLabel (itemLabel: string) => string Optional formatter for the drag handle's accessible name. Default: "Reorder {itemLabel}".
handle snippet Optional snippet rendered inside the drag-handle button. Receives { pressed, label }.
onReorder (nextItems: Item[], change: import('../../utilities/sortable-controller.types.ts').SortableReorderChange, ) => void req Fires with the full reordered array and change metadata on drop.
announcements Partial<import('../../utilities/sortable-controller.types.ts').SortableAnnouncements > Optional overrides for announcement strings.
children snippet req Row content snippet. Receives the item and a per-row context.
label text Accessible name for the list (applied as aria-label on the list root).