shadcn.io is not affiliated with official shadcn/ui
Reorder Items Dialog Block for React
A landing-page builder's reorder dialog shown open: five page sections with grips you lift with Space and move with the arrow keys, Move up and down buttons, a spoken position, and the page behind it rearranging on save.
Installation
Overview
Let people put things in order without a mouse, with this reorder dialog for React with Base UI. It opens from the Home page of Brickfold, a landing-page builder: the page's header holds an outline Reorder sections Button, and the page itself, a browser frame with five labelled bands, Hero, Logos, Features, Pricing and FAQ, is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The Dialog lists the five sections as rows, each with a grip that is a real button, a position number, the section's name and one line about it, and Move up and Move down buttons. Focus a grip and Space lifts the row, the arrow keys, Home and End move it, Space drops it and Escape puts it back, while a line under the list says where it is, "Pricing moved to position 2 of 5". A pointer can drag the same grip. Reset order goes back to the order Brickfold ships with, and the only Shine Button, Save order, rearranges the bands of the drawn page. For preview the dialog is drawn open in place when the page loads; the header button opens the real Dialog, with the same list. For page builders, menus, playlists and any list whose order is the content.
FAQ
Why is the dialog already open, and what do I keep?
So you can see it without a click. On load the dialog is a copy drawn in place over the page: a native dialog element that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The Reorder sections button opens the real Dialog, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same OrderBody component and share the block's state, so what you moved in the copy is there in the real one. In your app keep the Dialog and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.
How do the keys work, and what does Escape do?
Tab to a row's grip. Space or Enter lifts it (the grip shows as pressed and a line says "Lifted Pricing, position 4 of 5"), Up and Down move it one place, Home and End send it to the first or last place, and Space or Enter drops it. Escape while a row is lifted puts the list back as it was when you lifted it and keeps the dialog open; a second Escape closes the dialog. Focus stays on the grip as the row moves, and each move is said in a polite message with the new position out of five.
What about touch and the mouse?
Every row has Move up and Move down buttons, which are the whole interaction for a phone and for anyone who prefers pressing to holding: focus stays on the button you pressed, or moves to its partner when the row reaches an end. The grip also takes a pointer drag, written with pointer events and a transform, no drag library: the row follows the pointer, the others step aside, and releasing drops it. Drag is the extra, never the only way.
What is saved, and how do I wire it up?
Nothing leaves the tab. Save order copies the order into the drawn page's bands and says so in a polite message, and says "nothing to save" when the order is unchanged. Reset order goes back to the shipped order, and Cancel or Escape throws the unsaved order away. In your app keep the list of ids in state as here and post it from save; the server's order is the one to render back.
Is it accessible from the keyboard and a screen reader?
Yes. The real dialog is named by its title and described by its sentence, focus starts on the first grip and stays inside until it closes, and Escape, Cancel and the close button return focus to Reorder sections. Every grip is named with its section and position, "Reorder Pricing, position 4 of 5", and described by the key instructions, so nothing depends on seeing the drag. The trigger is passed to DialogTrigger through render, and the dialog is controlled with open and onOpenChange. The copy shown on load moves no focus; Escape inside it, Cancel and its close button close it and put focus on the button.
Related
- 12Pro
Sort Options Dialog
Notes and editingA data-grid tool's sort dialog shown open: up to three rules with a field and a direction each, Move up, Move down and Remove, a sorted five-row preview with the sorted columns numbered, and the table re-sorting on apply.
- Pro
Reorderable Digest Changelog
Votes and sharingA list of five digest sections with Move up and Move down buttons and a pointer-drag grip; a drawn digest preview follows the order, and each move is announced.
- Pro
Drag To Reorder Gallery
Select and actEight drawn portfolio pages in a framed grid that you reorder by dragging a grip, by Space and the arrow keys, or with Move earlier and Move later buttons, with every move announced and logged.
- Pro
A priority backlog you reorder by dragging a grip or pressing Move up and Move down, with a live numbered Order list beside it and the new position announced after every move.
- Pro
Column Reorder Table
Columns and pagingA pipeline table with a Column order list beside it: Move earlier and Move later buttons reorder the columns and announce the move, a grip drags as an extra, and Reset restores the default order.
- Pro
Filter Sort Dialog
Side sheetsA vinyl shop's records page with its filter panel shown open as a sheet from the start edge: genre chips, a decade list, a two-thumb price range, conditions, an in-stock switch and a sort order, all changing the grid behind it as you touch them.