- Add the registry
- Add sortable
Usage
Pass Sortable your items as value and render a SortableItem for each, in the same order,
with the item's unique value. That's the item itself for strings and numbers, or else its id, and
getItemValue returns another. When an item is dropped somewhere new, onValueChange gets the
items in their new order.
People drag an item by its SortableHandle, or by the whole item when it has no handle. As an item
moves, the others slide aside to open its place, and it settles into the place when it's dropped.
Dragging near the edge of the page, of a box the list sits in, or of the list itself when it
scrolls, scrolls it.
Each handle, or each item without one, is a stop in the tab order. Space or Enter picks an item
up, the arrow keys along the list move it, and Home and End move it to the start or end. Space or
Enter drops it, and Escape, or moving focus away, puts it back. Screen readers that activate
controls with a click, as VoiceOver and TalkBack do, pick an item up and drop it the same way.
They hear where the item is as it moves, and label on a SortableItem names it, in place of
its text.
Sortable lays the items out in a column, or a row with orientation="horizontal", and gives
the items no look of their own. Render each as an Item, or anything with a
background, since a lifted item passes over the others. It's a list and its items are list items,
unless it's rendered as part of a table or its items have no handles, since an item without a
handle is a button.
Composition
Examples
Without a handle
Leave out SortableHandle to drag the whole item. On a touch screen, people hold the item for a
moment first, so swiping across the list still scrolls the page. The item is then a button, which
screen readers read as one piece, so keep controls out of it.
Horizontal
orientation="horizontal" runs the items in a row, which the left and right arrow keys move along.
Columns show in the order Name, Status, Owner, Due.
Interactive content
Give an item that holds buttons, switches, links or fields a SortableHandle. Its controls then
work as usual, and the handle moves it.
Disabled
disabled on a SortableItem keeps that item where it is while the others move around it.
disabled on Sortable keeps every item in place.
Table rows
Render Sortable as a Table's TableBody, and each item as a TableRow.
Sortable then leaves the layout and the roles to the table, with or without handles. A row's border goes by its place
in the table, which only changes on the drop, so this example gives every row a border while one
is lifted.
In a form
Give a Field or Sortable a name, and each item's value submits under it in order, so
formData.getAll(name) reads the ranking. Pass form with a form's id when the list sits
outside it. With a Form, onFormSubmit gets the values as an array. A FieldLabel names the
list, and the field's description and errors are read out with it. An item mid-drag submits from
where it was until it's dropped. A form reset puts the items back in the order they first had,
through onValueChange with the reason reset. A disabled Sortable still submits its order.
Scrolling
A list in a Scroll Area scrolls while an item is dragged near its top or bottom, and moving an item with the keyboard keeps it in view.
Saving the order
onValueChange runs once per drop, and only when the order changed. Its second argument has the
reason move, and says which item moved and its index before and after, for saving the move. The items wait in their new
places for the new order, so it can arrive a moment later, as from a transition. If it hasn't
after a second, they slide back.
Move a metric to save the order.
Props
SortableHandle shows a grip until you pass it children of your own. An item's data-dragging
attribute marks it while it's lifted, and data-dropping while it settles.
The tables leave out className, style and render. Parts built on Base UI take them as its styling and composition guides describe.