Build an accessible reorderable list
One pure move operation can support drag, buttons, direct position, keyboard acceleration, focus retention, announcements, persistence, and undo.
Drag and drop is a presentation of reordering, not the reordering operation itself.
If moving an item requires holding a pointer while tracking a target, the product has confused one input method with the user's goal. The same operation can be exposed through move buttons, a destination menu, keyboard shortcuts, or a position field.
WCAG 2.2 guidance for dragging movements explicitly describes stepwise controls and position inputs as alternatives for reorderable lists.
We will build one pure moveItem(from, to) operation, then connect several accessible controls to it while preserving focus, announcing results, and supporting undo.
The durable part is the state transition. Dragging is one adapter.
Pointer, keyboard, button, voice command, or position field resolves a stable item key—not a fragile DOM index.
The shared operation validates destination, produces the next ordered keys, and records an inverse for undo.
Keep focus with the moved item, announce its new position, persist the order, and expose recovery.
Model reordering as data
Represent order as stable item keys and implement a pure move operation before adding pointer or keyboard behavior.
I would pressure-test that decision with four questions:
- What identifies an item?
- Is destination an index or neighbor?
- What invalid moves exist?
- Can the inverse be computed?
The failure mode here is moving DOM nodes directly and treating the screen as source of truth. In ranked lists, priorities, playlists, navigation, kanban columns, and configuration screens where drag interaction can exclude keyboard, touch, switch, voice, tremor, zoom, and screen-reader users or obscure the final order, that can hide the exact boundary a reviewer or teammate needs to understand. My working artifact would be a tested moveItem function. I want it close enough to the implementation that it can change the work, not created afterward to decorate the story.
The result I would look for is one deterministic operation for every input. That is a narrower claim than saying the whole system improved, but it is also one I can verify and defend.
In practice, I would put a tested moveItem function beside the question “What identifies an item?” before the first implementation review. The next pass would use “Is destination an index or neighbor?” to test the boundary, then “What invalid moves exist?” to expose the state most likely to be missed. I would keep “Can the inverse be computed?” for the release check because it asks whether the decision still holds outside the ideal path. The work is ready to move when the artifact can explain the choice and the observed result supports one deterministic operation for every input.
Start with semantic structure
Use a real list with clearly named items and ordinary buttons so reading order and available actions exist before enhancement.
The practical review starts here:
- Is this an ordered list?
- Does each item have a name?
- Are actions real buttons?
- Is current position available?
Those questions keep starting with generic divs and draggable attributes from becoming the default. I would capture the decision in a no-drag semantic baseline, then use it while the work is still cheap to change. For input-independent list reordering, the artifact should make ownership, constraint, and next action visible without requiring a private explanation.
Success would look like usable reordering without pointer gestures. If I cannot point to that evidence, I have a direction, not a finished decision.
The implementation move is to make a no-drag semantic baseline part of the working surface. I would use it to answer “Is this an ordered list?” while scope is still flexible, and “Does each item have a name?” before code or content becomes expensive to unwind. During QA, “Are actions real buttons?” and “Is current position available?” become concrete checks rather than discussion prompts. That sequence turns input-independent list reordering into something the team can operate and gives me a specific outcome to report: usable reordering without pointer gestures.
- IdleControls are discoverable
Item label, position, handle purpose, move actions, and disabled boundaries are understandable.
- MovingDestination is clear
Pointer preview or keyboard mode identifies the active item and available positions without hiding the list.
- PlacedOutcome is confirmed
Focus follows the item, position is announced, save state is visible, and undo remains available.
Add stepwise move controls
Move up and down controls provide a direct alternative and should disable only at genuine boundaries.
Before implementation, I would answer:
- Is the action label specific?
- What happens at first and last?
- Can controls stay compact?
- Do disabled states explain themselves?
The artifact is per-item move controls with accessible names. Its job is to expose the tradeoff early enough that design, engineering, support, or product can disagree with something concrete. The common trap is hiding alternative controls until drag fails; it moves uncertainty downstream and makes the final interface carry a problem the system never resolved.
For me, the useful receipt is single-pointer and keyboard-compatible movement. That connects one reorder model exposed through drag, move buttons, keyboard commands, position input, announcements, and undo to an observable result instead of a process claim.
I would test this with one typical case and one boundary case. The typical case should make “Is the action label specific?” easy to answer. The boundary should force a decision about “What happens at first and last?” and “Can controls stay compact?.” I would record both in per-item move controls with accessible names, including the part that stayed unresolved after the first pass. The final check, “Do disabled states explain themselves?,” is where the artifact earns its place: it either supports single-pointer and keyboard-compatible movement, or it shows exactly why another iteration is needed.
Support direct destination
Long lists need a faster path such as move to beginning, end, before item, or numeric position.
I would use these prompts during the working review:
- How long can the list become?
- Which destinations are meaningful?
- How are invalid positions handled?
- Does filtering change numbering?
If the team slips into forcing twenty move-up clicks for one operation, the product can still look complete while its operating rule stays ambiguous. I would make a move-to-position control the shared reference and keep it small enough to update as evidence changes.
The standard is efficient placement independent of drag precision. That tells me whether the decision helped the product, not merely whether the document was completed.
The working sequence is small: draft a move-to-position control, review it against “How long can the list become?,” implement the narrowest useful path, and then return with evidence for “Which destinations are meaningful?.” I would use “How are invalid positions handled?” to inspect product consequence and “Does filtering change numbering?” to decide whether the result is stable enough to ship. This keeps forcing twenty move-up clicks for one operation visible as a known risk and makes efficient placement independent of drag precision the release receipt rather than a hopeful conclusion.
| Signal | Decision | Working note |
|---|---|---|
| Buttons | Move up or down | Simple, visible, single-pointer controls work well for short lists and motor-access alternatives. |
| Destination | Move to position | A menu or numeric control avoids dozens of repeated clicks in long lists and supports direct placement. |
| Keyboard | Pick up and place | A documented shortcut can accelerate expert use while standard buttons remain available. |
Layer pointer drag carefully
Pointer drag should preview the active item and target, handle cancellation, auto-scroll conservatively, and finish through the shared move operation.
I would pressure-test that decision with four questions:
- What starts a drag?
- How is the target shown?
- Can the user cancel?
- What happens outside the list?
The failure mode here is making the entire row draggable and breaking text selection. In ranked lists, priorities, playlists, navigation, kanban columns, and configuration screens where drag interaction can exclude keyboard, touch, switch, voice, tremor, zoom, and screen-reader users or obscure the final order, that can hide the exact boundary a reviewer or teammate needs to understand. My working artifact would be a pointer-state adapter with cancel path. I want it close enough to the implementation that it can change the work, not created afterward to decorate the story.
The result I would look for is an optional drag experience with clear boundaries. That is a narrower claim than saying the whole system improved, but it is also one I can verify and defend.
In practice, I would put a pointer-state adapter with cancel path beside the question “What starts a drag?” before the first implementation review. The next pass would use “How is the target shown?” to test the boundary, then “Can the user cancel?” to expose the state most likely to be missed. I would keep “What happens outside the list?” for the release check because it asks whether the decision still holds outside the ideal path. The work is ready to move when the artifact can explain the choice and the observed result supports an optional drag experience with clear boundaries.
Design keyboard acceleration
Keyboard commands should be documented, avoid colliding with expected navigation, and never become the only accessible route.
The practical review starts here:
- Which key enters move mode?
- How is the active item identified?
- What places or cancels?
- Where is help exposed?
Those questions keep inventing shortcuts without discoverability or cancellation from becoming the default. I would capture the decision in a small keyboard interaction contract, then use it while the work is still cheap to change. For input-independent list reordering, the artifact should make ownership, constraint, and next action visible without requiring a private explanation.
Success would look like fast expert movement with a visible baseline. If I cannot point to that evidence, I have a direction, not a finished decision.
The implementation move is to make a small keyboard interaction contract part of the working surface. I would use it to answer “Which key enters move mode?” while scope is still flexible, and “How is the active item identified?” before code or content becomes expensive to unwind. During QA, “What places or cancels?” and “Where is help exposed?” become concrete checks rather than discussion prompts. That sequence turns input-independent list reordering into something the team can operate and gives me a specific outcome to report: fast expert movement with a visible baseline.
Retain focus on the item
After reordering, focus belongs with the moved object's control, not the old numeric position or the document body.
Before implementation, I would answer:
- Which element owns focus?
- Does the key remain stable?
- What if the item leaves view?
- What happens after undo?
The artifact is a focus restoration rule keyed by item ID. Its job is to expose the tradeoff early enough that design, engineering, support, or product can disagree with something concrete. The common trap is using array indexes as React keys; it moves uncertainty downstream and makes the final interface carry a problem the system never resolved.
For me, the useful receipt is continuous orientation across DOM movement. That connects one reorder model exposed through drag, move buttons, keyboard commands, position input, announcements, and undo to an observable result instead of a process claim.
I would test this with one typical case and one boundary case. The typical case should make “Which element owns focus?” easy to answer. The boundary should force a decision about “Does the key remain stable?” and “What if the item leaves view?.” I would record both in a focus restoration rule keyed by item ID, including the part that stayed unresolved after the first pass. The final check, “What happens after undo?,” is where the artifact earns its place: it either supports continuous orientation across DOM movement, or it shows exactly why another iteration is needed.
Announce outcome, not motion noise
Assistive technology needs a concise result such as item name and new position, while pointer hover over every target should remain quiet.
I would use these prompts during the working review:
- Which change needs announcement?
- Is role=status appropriate?
- Does the item label appear?
- Can rapid moves be coalesced?
If the team slips into announcing every pixel or drop-target transition, the product can still look complete while its operating rule stays ambiguous. I would make a polite live-region message pattern the shared reference and keep it small enough to update as evidence changes.
The standard is useful confirmation without audio overload. That tells me whether the decision helped the product, not merely whether the document was completed.
The working sequence is small: draft a polite live-region message pattern, review it against “Which change needs announcement?,” implement the narrowest useful path, and then return with evidence for “Is role=status appropriate?.” I would use “Does the item label appear?” to inspect product consequence and “Can rapid moves be coalesced?” to decide whether the result is stable enough to ship. This keeps announcing every pixel or drop-target transition visible as a known risk and makes useful confirmation without audio overload the release receipt rather than a hopeful conclusion.
Persist with conflict behavior
Saving order should include a collection revision or equivalent precondition because two editors can reorder the same list concurrently.
I would pressure-test that decision with four questions:
- What version is being edited?
- Can save conflict?
- Is optimistic update safe?
- How is merge or reload explained?
The failure mode here is last-write-wins persistence with no conflict signal. In ranked lists, priorities, playlists, navigation, kanban columns, and configuration screens where drag interaction can exclude keyboard, touch, switch, voice, tremor, zoom, and screen-reader users or obscure the final order, that can hide the exact boundary a reviewer or teammate needs to understand. My working artifact would be a versioned order mutation and recovery state. I want it close enough to the implementation that it can change the work, not created afterward to decorate the story.
The result I would look for is durable order without silent overwrites. That is a narrower claim than saying the whole system improved, but it is also one I can verify and defend.
In practice, I would put a versioned order mutation and recovery state beside the question “What version is being edited?” before the first implementation review. The next pass would use “Can save conflict?” to test the boundary, then “Is optimistic update safe?” to expose the state most likely to be missed. I would keep “How is merge or reload explained?” for the release check because it asks whether the decision still holds outside the ideal path. The work is ready to move when the artifact can explain the choice and the observed result supports durable order without silent overwrites.
Test every input and recovery path
QA should cover buttons, keyboard, pointer, touch, zoom, screen readers, long labels, filtered lists, save failure, conflict, undo, and focus.
The practical review starts here:
- Can every move happen without drag?
- Is focus preserved?
- Is the announcement accurate?
- Does failure restore the prior order?
Those questions keep testing only a mouse drag in the ideal list from becoming the default. I would capture the decision in a cross-input reorder test matrix, then use it while the work is still cheap to change. For input-independent list reordering, the artifact should make ownership, constraint, and next action visible without requiring a private explanation.
Success would look like evidence that reordering belongs to every user. If I cannot point to that evidence, I have a direction, not a finished decision.
The implementation move is to make a cross-input reorder test matrix part of the working surface. I would use it to answer “Can every move happen without drag?” while scope is still flexible, and “Is focus preserved?” before code or content becomes expensive to unwind. During QA, “Is the announcement accurate?” and “Does failure restore the prior order?” become concrete checks rather than discussion prompts. That sequence turns input-independent list reordering into something the team can operate and gives me a specific outcome to report: evidence that reordering belongs to every user.
What I would show in the work
The public version needs evidence from the work itself. For this topic, the first five artifacts I would reach for are:
- a tested moveItem function
- a no-drag semantic baseline
- per-item move controls with accessible names
- a move-to-position control
- a pointer-state adapter with cancel path
I would not publish all five at equal weight. One should orient the reader, one should reveal the hardest tradeoff, and one should prove the result. The others can live in a downloadable note or appear as supporting frames. That edit matters because one reorder model exposed through drag, move buttons, keyboard commands, position input, announcements, and undo becomes harder to understand when every process detail is treated as equally important.
I would also show one rejected direction. The useful version is specific: which option looked attractive, which constraint made it wrong, and what evidence supported the narrower choice. That gives an engineering manager something real to question and keeps the case study from reading like the final answer was obvious from the beginning.
# state order = [a7, c2, b4] Rendered positions derive from key order; item content and focus identity do not depend on array index.
# move moveItem(c2, 0) Return [c2, a7, b4], inverse moveItem(c2, 1), and announcement 'Moved Billing to position 1 of 3'.
# save PATCH order with revision Optimistic update, conflict response, rollback or merge, visible saving state, and retry without another move.
Resource path
The practical follow-up I would build is an accessible reorderable-list starter with semantic list structure, stable keys, move operation, pointer drag, button alternative, keyboard map, focus retention, live announcements, undo, persistence, and tests. I am treating that as a resource backlog item, not pretending the adjacent downloads below are the same artifact. The related cards cover useful pieces of the workflow today; this specific file should only be published when its examples, fields, and instructions are complete.
The first version should stay concise: context, constraint, decision, evidence, owner, and follow-up. Its value would come from helping someone repeat this exact review, not from adding another generic PDF to the site.
Review checklist
The article-specific review questions are:
- What identifies an item?
- Is this an ordered list?
- Is the action label specific?
- How long can the list become?
- What starts a drag?
- Which key enters move mode?
- Which element owns focus?
- Which change needs announcement?
- What version is being edited?
- Can every move happen without drag?
I would add two editorial checks before publishing: can a recruiter find the point in the first minute, and can an engineer trace at least one claim to an implementation or production receipt? If either answer is no, the article needs another edit.
Implementation notes
For input-independent list reordering, I would write the implementation note before polish. It would name the changed surface, source of truth, owner, failure boundary, and verification path. Those details prevent the principle from floating above the actual code or operational workflow.
The proof signals I care about are specific to this article:
- fast expert movement with a visible baseline
- continuous orientation across DOM movement
- useful confirmation without audio overload
- durable order without silent overwrites
- evidence that reordering belongs to every user
I would choose two or three of those signals for the first release rather than instrumenting everything. The strongest pair usually combines one direct behavior check with one operating check: a route and a data query, a keyboard path and a support state, a handler replay and a reconciliation result, or a migration count and a rendered screen.
The follow-up belongs in the note before shipping. It should say what remains temporary, what evidence would trigger another pass, and who owns that decision. That is how the first version stays intentionally narrow without making the boundary invisible.
Case-study packaging
I would structure the case-study version around the four visual lessons already established:
- Every input method should call the same reorder operation.
- Reordering has observable interaction states.
- Alternatives should preserve the same product capability.
- Stable keys keep focus and persistence aligned.
The opening frame explains the product pressure. The middle two show the decision moving through the system. The last frame is the receipt: what was checked, what held, and what remained unresolved. That order lets the reader move from product judgment into implementation detail without reconstructing the whole project first.
I would include one caveat tied to ranked lists, priorities, playlists, navigation, kanban columns, and configuration screens where drag interaction can exclude keyboard, touch, switch, voice, tremor, zoom, and screen-reader users or obscure the final order: a data limit, rollout boundary, unsupported state, external dependency, or result that is still directional. A precise caveat makes the evidence easier to trust because it shows where the claim stops.
The final test is whether the page creates a better conversation. If the artifact helps someone ask a sharper question about product judgment, implementation detail, or release proof in a live interview, it belongs in the story.
Interview angle
In an interview, I would explain this through one reorder model exposed through drag, move buttons, keyboard commands, position input, announcements, and undo. The story should start with the product pressure, then move into the system constraint, the artifact, and the proof. That order keeps the answer grounded. It also gives the interviewer several places to go deeper: data, frontend architecture, design systems, support, migration, accessibility, or release process.
The strongest version of the answer includes a tradeoff. I want to be able to say what I chose, what I left alone, and how I knew the work helped. That is more credible than presenting every project as a clean win.
The hiring signal
An accessible reorderable list is a hiring signal because it shows I can separate a product operation from one fashionable input method and preserve state, focus, and recovery across implementations.
That is the level I want this site to communicate. The work should show taste, but it should also show operating judgment. It should make me look like someone who can enter a real product system, understand the messy middle, ship the useful version, and leave enough proof for the next person to trust it.
Use this after reading.
Practical downloads and templates that turn the article into something you can bring into a product review, implementation pass, or agent workflow.
Front-End State Recipes
Reusable recipes for optimistic actions, loading, empty, error, data-transition, and disabled-control states.
Design System Contribution Pack
A contribution brief, drift diagnosis, escape-hatch rules, and component-docs template for product teams.
UI PR Risk Review Checklist
A merge-readiness checklist for product intent, states, accessibility, visual durability, and UI implementation risk.