Vertical list reordered by drag handle or keyboard, with announcements
Tags: component list reorder drag
SortableList renders a list whose items people can reorder - questions, options, slides, steps. Each item renders its own drag handle by spreading handle on a button. The list never changes items itself; it calls onReorder(from, to).
Import
<script>
import { SortableList } from '@classic-homes/theme-svelte';
</script>Basic Usage
<script>
import { SortableList, Icon } from '@classic-homes/theme-svelte';
let steps = $state([
{ id: 'a', label: 'Frame inspection' },
{ id: 'b', label: 'Drywall' },
{ id: 'c', label: 'Final walk' },
]);
function move(from, to) {
const [item] = steps.splice(from, 1);
steps.splice(to, 0, item);
}
</script>
<SortableList
items={steps}
getKey={(s) => s.id}
getItemLabel={(s) => s.label}
onReorder={move}
label="Steps"
class="space-y-1"
>
{#snippet item({ item, handle, dragging })}
<div class="flex items-center gap-2 rounded border p-2" class:shadow-lg={dragging}>
<button {...handle} class="cursor-grab touch-none"><Icon name="grip" size={14} /></button>
{item.label}
</div>
{/snippet}
</SortableList>Props
| Prop | Type | Default | Description |
|---|---|---|---|
items |
T[] |
required | Items in order (required) |
getKey |
(item, index) => string | number |
required | Stable key (required) |
onReorder |
(from: number, to: number) => void |
required | Move item from to index to (required) |
item |
Snippet<[{ item, index, handle, dragging }]> |
required | Renders one item (required) |
label |
string |
required | Accessible name of the list (required) |
getItemLabel |
(item, index) => string |
"Item n" |
Name used in announcements and handle labels |
disabled |
boolean |
false |
Turns reordering off |
class |
string |
- | Classes for the ul |
itemClass |
string |
- | Classes for each li |
Keyboard Navigation
Space/Enteron a handle - Pick up / dropArrowUp/ArrowDown- Move the picked-up itemHome/End- Move it to the start / endEscape- Cancel and put it backAlt+ArrowUp/Alt+ArrowDown- Move one step without picking up
Accessibility
- Handles are buttons named "Reorder {item}" with
aria-pressedwhile picked up and instructions linked byaria-describedby. - Every move, drop and cancel is announced in a live region.
- Pointer capture is taken on the handle only, so clicks elsewhere in the item keep working.
Related Components
- Studio - Its outline is a SortableList