Sortable Stack
List the user can reorder by dragging or keyboard.
Installation
pnpm dlx shadcn@latest add @paneui/sortable-stackUsage
Composition
Examples
Keyboard
Rows move only from their handle. With a handle focused, Up/Down move the row one step and Home/End send it to the top or bottom; focus stays on the handle and the new position is announced.
Motion
The dragged row scales to 1.025. With reduced motion rows jump into place without scaling.
SortableStack
Drag-to-reorder list. Items need a string id.
- items
- T[]
- Controlled rows in order.
- defaultItems= []
- T[]
- Initial rows when uncontrolled.
- onItemsChange
- (items: T[]) => void
- Called with the new order after a drag, key move or undo.
- getItemLabel*
- (item: T) => string
- Readable name per row, used in handle labels and announcements.
- children*
- (items: T[]) => ReactNode
- Render the rows in their current order.
- label= "Sortable list"
- string
- Accessible name of the list.
- disabled= false
- boolean
- Lock the order; handles are disabled and rows can't be dragged.
- showUndo= true
- boolean
- Render the Undo pill under the list.
- footer
- ReactNode
- Extra content under the list, inside the stack's context.
- className
- string
- Merged onto the wrapper.
| Prop | Type | Default | Description |
|---|---|---|---|
| items | T[] | — | Controlled rows in order. |
| defaultItems | T[] | [] | Initial rows when uncontrolled. |
| onItemsChange | (items: T[]) => void | — | Called with the new order after a drag, key move or undo. |
| getItemLabel* | (item: T) => string | — | Readable name per row, used in handle labels and announcements. |
| children* | (items: T[]) => ReactNode | — | Render the rows in their current order. |
| label | string | "Sortable list" | Accessible name of the list. |
| disabled | boolean | false | Lock the order; handles are disabled and rows can't be dragged. |
| showUndo | boolean | true | Render the Undo pill under the list. |
| footer | ReactNode | — | Extra content under the list, inside the stack's context. |
| className | string | — | Merged onto the wrapper. |
SortableStackItem
One row.
- id*
- string
- The item's id.
- className
- string
- Merged onto the row.
- style
- CSSProperties
- Inline style for the row.
- children
- ReactNode
- Handle and content.
| Prop | Type | Default | Description |
|---|---|---|---|
| id* | string | — | The item's id. |
| className | string | — | Merged onto the row. |
| style | CSSProperties | — | Inline style for the row. |
| children | ReactNode | — | Handle and content. |
- data-dragging
- Present while the row is dragged.
| Data attribute | Description |
|---|---|
| data-dragging | Present while the row is dragged. |
SortableStackHandle
Grip button that starts the drag and owns keyboard reordering. Labelled with the row's name and position. Also accepts every prop of button.
- children= grip icon
- ReactNode
- Replace the grip icon.
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | grip icon | Replace the grip icon. |
SortableStackUndo
Restores the order from before the last move. Hidden until there is something to undo. Also accepts every prop of button.
- data-visible
- Present while an undo is available.
| Data attribute | Description |
|---|---|
| data-visible | Present while an undo is available. |
useSortableStack
Order and actions for custom controls. Use inside SortableStack.
- ids
- string[]
- Current order of ids.
- moveItem
- (id: string, by: -1 | 1 | "first" | "last") => void
- Move a row; undoable.
- undo
- () => void
- Restore the previous order.
- canUndo
- boolean
- Whether an undo is available.
- disabled
- boolean
- Whether the stack is disabled.
| Prop | Type | Default | Description |
|---|---|---|---|
| ids | string[] | — | Current order of ids. |
| moveItem | (id: string, by: -1 | 1 | "first" | "last") => void | — | Move a row; undoable. |
| undo | () => void | — | Restore the previous order. |
| canUndo | boolean | — | Whether an undo is available. |
| disabled | boolean | — | Whether the stack is disabled. |