Layout & display
SortableList
A list a person puts in order. A row moves when its handle is dragged, from the handle's menu, or with Alt and an arrow key, and every move is announced in the row's own words.
Basic
Bind items and a move writes the new order back. Each item carries an id and a label. The rows are keyed by the id, so it has to be stable and
unique in the list, and a repeated id throws in development. The label names the row's handle and
every sentence a move announces. The row snippet draws what sits beside the handle, and
it receives the item and its index.
- 1. Hero Image and heading
- 2. Features Three columns
- 3. Pricing Plan table
- 4. FAQ Questions
- 5. Footer Links
Press Alt with the up or down arrow to move a row, or Enter for a menu.
hero, features, pricing, faq, footerFrom the keyboard
Tab reaches each row's handle. Alt with the up or down arrow moves the row that holds the focus, and the focus stays on its handle, so the next press moves the row again. Alt is Option on a Mac. Enter, Space or an arrow alone opens the handle's menu, whose Move up and Move down make the same moves. During a drag, Escape puts the row back where it started.
The keys work from anywhere in the row, so a row that draws its own controls needs no extra tab
stop. Alt with an arrow pressed in a text field stays with the field, where Option and an arrow
move the caret on macOS. A control in the row that handles the key itself and calls preventDefault keeps it too.
With a pointer
A mouse lifts a row once it moves a few pixels with the button down. A finger lifts it after resting a quarter of a second on the handle, so a swipe that starts on a handle still scrolls the page. The lifted row follows the pointer, a line marks where it will land, and the box that scrolls the list scrolls when the pointer nears its edge. Escape or a second finger puts the row back.
A click or a tap on the handle that lifts nothing opens the menu. That is the way in for a pointer that cannot drag and for a screen reader on a phone. A drag follows its row by id, so a list that changes during a drag still moves the row that was lifted, and removing that row ends the drag.
What a screen reader hears
The list is named by label. Each handle reads "Move" and the row's label, and its
description names the keys. Every move, and every move that cannot happen, is said in a polite
live region: "Hero moved to position 2 of 5.", "Hero is already first.", or the sentence canMove returned.
Refusing a move and saving the order
canMove is asked before every move, whether it comes from a drag, a key or the menu.
It returns true to allow the move, or the sentence to announce in its place. While a
lifted row is over a refused place, the line turns to the danger tone and a drop there puts the
row back. onmove is called once a move has landed, with the row, the index it left, the index
it reached and the whole list in its new order, which items already holds. It is the place
to save the order.
- Hero
- Features
- Pricing
- FAQ
- Footer
Press Alt with the up or down arrow to move a row, or Enter for a menu.
API
| Prop | Type | Default | Description |
|---|---|---|---|
items required | T[] | no default | The rows, in order. Bindable, and a move writes the new order back. |
label required | string | no default | Names the list for a screen reader. |
row required | Snippet<[T, number]> | no default | Draws a row's content beside its handle, from the item and its index. |
canMove | (item: T, from: number, to: number) => true | string | no default | Allows a move with true, or refuses it with the sentence to announce instead. |
onmove | (move: SortableMove<T>) => void | no default | Called once a move has landed, when items already holds the new order. |
class | string | no default | Extra classes on the wrapper. |
SortableItem
T is any type that extends SortableItem, so an item can carry whatever
the row draws.
| Prop | Type | Default | Description |
|---|---|---|---|
id required | string | no default | Stable, and unique in the list. A changed id remounts its row. |
label required | string | no default | The row's name: its handle reads "Move" and the label, and moves announce it. |
SortableMove
| Prop | Type | Default | Description |
|---|---|---|---|
item required | T | no default | The row that moved. |
from required | number | no default | The index it left. |
to required | number | no default | The index it reached. |
items required | T[] | no default | The list in its new order, which items holds as well. |