Sortable List React component
A list people can put in their own order: drag a row by its handle and the others slide out of the way, or use the keyboard (Space to lift, arrows to move, Space to drop, Escape to undo), with live position numbers and optional remove buttons.
When to use the Sortable List component
Use Sortable List wherever order is the user's decision: agendas, playlists, priorities, menu items, form fields, steps in a flow. Dragging from the handle keeps the rest of the row free for scrolling on touch screens.
Save the new order from onValueChange; the component only reorders what you give it.
Installation
Add the Sortable List component to your project with the shadcn CLI. It lands in components/sortable-list.tsx as plain React + Tailwind CSS source you own and can edit.
npx shadcn@latest add https://reactframe.com/r/sortable-list.jsonOr copy the source by hand and install its dependencies:
npm install motion clsx tailwind-mergeProps
<SortableList /> accepts 8 props, all optional.
| Prop | Type | Default |
|---|---|---|
| items | { id: string; title: string; meta?: string }[] | DEFAULT_ITEMS |
| value Controlled order. | { id: string; title: string; meta?: string }[] | — |
| onValueChange | (items: SortableItem[]) => void | — |
| showNumbers Show 1, 2, 3 ... in front of each row (they update as rows move). | boolean | true |
| removable A remove button on each row. | boolean | false |
| label | string | "Agenda" |
| theme | "dark" | "light" | "dark" |
| className | string | — |
- items{ id: string; title: string; meta?: string }[]Default: DEFAULT_ITEMS
- value
Controlled order.
{ id: string; title: string; meta?: string }[] - onValueChange(items: SortableItem[]) => void
- showNumbers
Show 1, 2, 3 ... in front of each row (they update as rows move).
booleanDefault: true - removable
A remove button on each row.
booleanDefault: false - labelstringDefault: "Agenda"
- theme"dark" | "light"Default: "dark"
- classNamestring
FAQ
- Can it be sorted without a mouse?
- Yes. Tab to a row's handle, press Space to lift it, move it with the up and down arrows, and press Space to drop or Escape to put it back. Each step is announced to screen readers.
- Why drag from a handle?
- So the rest of the row can still be scrolled, selected or clicked, which matters most on phones.
- Can people remove rows?
- Set removable to add a × button on each row; the row collapses away and onValueChange receives the shorter list.