How to build an accessible ReorderList in React

Every row carries a real button as its drag handle, so the entire interaction is reachable by keyboard: Space or Enter picks a row up, ArrowUp/ArrowDown move it, Space or Enter drops it, and Escape restores the order captured at pick-up. The handle exposes aria-pressed so assistive technology can tell held from idle, and each transition — picked up, moved, dropped, cancelled — is announced through a polite role="status" region using interpolated catalog strings that carry the item name and its position out of the total. The handle sets touch-action: none so a touch drag is not stolen by the scroller, and meets the coarse-pointer target floor. Item names for announcements come from `name` when the label is not plain text, so a rich label never produces an empty announcement.

When to use a ReorderList

When not to use it

Keyboard interactions

Role list, verified at WCAG 2.2-AA.

Common mistakes

Avoid: Rendering a drag handle with no keyboard path

Prefer: Keep the built-in handle, which is a real button with Space/Arrow/Escape support

Pointer-only reordering is unusable by keyboard and screen-reader users; it is the standing accessibility gap in pointer-only implementations

Avoid: Deriving row keys from array index

Prefer: Give every item a stable `id`

Index keys make React reuse the wrong DOM nodes as rows move, so focus and animation land on the wrong row

Example

<ReorderList
  value={items}
  onValueChange={setItems}
/>

See the full ReorderList reference →