Flux 2.0

Component

Reorderable list

A list whose order is the meaning, rearranged by dragging a handle or with the keyboard.

Plain-text source, for agents and clipboard use: /components/source/reorder.txt

When to use it

Lets someone put items in order where the order matters: the days of an itinerary, the priority of suppliers, the sequence of a manifest. Each item has a handle that can be dragged, or focused and moved with the arrow keys; every move is announced, and the rest of the list settles into place rather than jumping.

Not this
Not for sorting by a value, such as date or price; that is a sortable Table column. Not for moving items between lists; that needs its own pattern. Not for long lists, where dragging past the screen is slow; offer a position field instead.

Examples

Day order

Drag a handle, or focus it, press Space, move with the arrow keys and press Space again. Escape puts the day back.

  1. Keflavík → Reykjavik 1 night
  2. Reykjavik → Vík 2 nights
  3. Vík → Jökulsárlón 1 night
  4. Jökulsárlón → Höfn 1 night

Press Space to pick up. Use the arrow keys to move, Space to drop, Escape to cancel.

html
<ol class="flux-reorder" data-flux-reorder aria-label="Day order">
  <li class="flux-reorder__item">
    <button class="flux-reorder__handle" type="button" aria-label="Move Keflavík → Reykjavik" aria-pressed="false" aria-describedby="reorder-help"><svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><circle cx="6" cy="4" r="1.1" /><circle cx="10" cy="4" r="1.1" /><circle cx="6" cy="8" r="1.1" /><circle cx="10" cy="8" r="1.1" /><circle cx="6" cy="12" r="1.1" /><circle cx="10" cy="12" r="1.1" /></svg></button>
    <span class="flux-reorder__label">Keflavík → Reykjavik</span>
    <span class="flux-reorder__meta">1 night</span>
  </li>
  <li class="flux-reorder__item">
    <button class="flux-reorder__handle" type="button" aria-label="Move Reykjavik → Vík" aria-pressed="false" aria-describedby="reorder-help"><svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><circle cx="6" cy="4" r="1.1" /><circle cx="10" cy="4" r="1.1" /><circle cx="6" cy="8" r="1.1" /><circle cx="10" cy="8" r="1.1" /><circle cx="6" cy="12" r="1.1" /><circle cx="10" cy="12" r="1.1" /></svg></button>
    <span class="flux-reorder__label">Reykjavik → Vík</span>
    <span class="flux-reorder__meta">2 nights</span>
  </li>
  <li class="flux-reorder__item">
    <button class="flux-reorder__handle" type="button" aria-label="Move Vík → Jökulsárlón" aria-pressed="false" aria-describedby="reorder-help"><svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><circle cx="6" cy="4" r="1.1" /><circle cx="10" cy="4" r="1.1" /><circle cx="6" cy="8" r="1.1" /><circle cx="10" cy="8" r="1.1" /><circle cx="6" cy="12" r="1.1" /><circle cx="10" cy="12" r="1.1" /></svg></button>
    <span class="flux-reorder__label">Vík → Jökulsárlón</span>
    <span class="flux-reorder__meta">1 night</span>
  </li>
  <li class="flux-reorder__item">
    <button class="flux-reorder__handle" type="button" aria-label="Move Jökulsárlón → Höfn" aria-pressed="false" aria-describedby="reorder-help"><svg viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><circle cx="6" cy="4" r="1.1" /><circle cx="10" cy="4" r="1.1" /><circle cx="6" cy="8" r="1.1" /><circle cx="10" cy="8" r="1.1" /><circle cx="6" cy="12" r="1.1" /><circle cx="10" cy="12" r="1.1" /></svg></button>
    <span class="flux-reorder__label">Jökulsárlón → Höfn</span>
    <span class="flux-reorder__meta">1 night</span>
  </li>
</ol>
<p class="flux-visually-hidden" id="reorder-help">Press Space to pick up. Use the arrow keys to move, Space to drop, Escape to cancel.</p>

Anatomy

PartDescription
ListAn ol, because the order is the meaning, labelled with aria-label.
ItemA row separated from the next by a hairline.
HandleA toggle button with a grip icon, named "Move <item>". The only part that drags.
LabelThe item’s name, used in every announcement.
MetaOptional mono detail that does not depend on position, such as "2 nights".

API

NameKindDescription
flux-reorderclassThe ol.
data-flux-reorderattributeWires dragging, keyboard moves, announcements and the settle. Requires flux-components.js.
flux-reorder__itemclassAn li. Carries data-lifted while it is picked up.
flux-reorder__handleclassA button with aria-pressed and aria-describedby pointing at the instructions.
flux-reorder__labelclassThe item name, read in announcements.
flux-reorder__metaclassOptional detail at the end of the row.
flux-reorder eventelementCancelable. Dispatched on the list after a drop that changed the order, with detail.item, detail.from and detail.to. A framework that renders the list cancels it: the item goes back where it started and the framework renders the new order.

States

StateTreatment
RestingRows on layer-01 with hairlines. The handle turns icon-brand on hover.
LiftedThe item takes surface-raised and --flux-reorder-lifted-shadow, because it floats above the list.
SettlingNeighbours slide into their new places over --flux-duration-fast, by transform only.

Keyboard

KeysAction
Space / EnterOn a handle, picks the item up; again, drops it.
↑ ↓While picked up, moves the item one place.
EscapeWhile picked up, returns the item to where it started.

Accessibility

  • Every pickup, move and drop is announced with the item’s name and position: "Reykjavik → Vík, position 3 of 4."
  • The handle is a real button, reachable with Tab, with aria-pressed showing whether its item is picked up.
  • Describe the keyboard controls once, in a visually hidden paragraph the handles reference.
  • Dragging is never the only way: the keyboard moves the same items, and a long list should also offer a position field.

Tokens

The tier-3 and tier-2 tokens this component binds to. Change the token, not the component.

  • --flux-reorder-divider | -padding-y | -gap
  • --flux-reorder-handle-size | -handle-icon
  • --flux-reorder-lifted-bg | -lifted-shadow

Do and don’t

Do

  • Save the new order as soon as it is dropped, and confirm with a Toast only if saving is not visible.
  • Keep position-dependent text, such as "Day 2", out of the label, or update it after every drop.

Don’t

  • Do not make the whole row draggable. Text in it must stay selectable and its links clickable.
  • Do not reorder on hover or animate the dragged item’s size. It lifts and moves; nothing grows.