Skip to content
Native Animation
Lift Reorder List animation preview

This preview uses fictional demo content. See the props below for the customization options available in this component.

npx nativeanimation add lift-reorder-list

Lift Reorder List

React Native Drag and Drop List with Lift and Reorder

A reorderable list with lifted rows and animated insertion space, with configurable items, row height, lifted color, and fonts.

$9 for this animation

Add to your project

Copy the component and its assets into your app with the Native Animation CLI, or paste the agent prompt into Claude Code, Codex or Cursor once the MCP server is connected.

About this animation

This React Native drag and drop list reorders rows inside a single list. Hold a row for 300 milliseconds or drag its grip immediately: the row lifts, tilts with velocity, and opens a gap as it crosses neighboring slots. Edge auto-scroll preserves its position under the finger. Releasing settles into the nearest slot; regrabbing interrupts the spring from its current position. Supply stable item IDs, title and subtitle content, and row dimensions. onOrderChange receives the new array after settling so your application can persist it. This is a reorderable queue rather than a cross-list drag-and-drop framework.

When to use it

  • Reorder a playback queue.
  • Prioritize a short task list.
  • Persist a user-defined row order.

Related guides

A reorderable list with lifted rows and animated insertion space, with configurable items, row height, lifted color, and fonts.

Why this one

Most reorder examples stop at translating one row. This version adds a two-layer depth treatment, velocity-driven tilt, immediate gap opening, edge auto-scroll, an interruptible release, and screen-reader move actions without using React state per frame.

How it works

  1. A single continuous shared position tracks the dragged row in row units.
  2. Neighboring rows derive their offsets when that position crosses their midpoint.
  3. A 300 ms hold starts dragging anywhere; the Lucide grip starts immediately.
  4. Edge proximity updates the scroll offset on the UI thread while preserving the finger-to-row relationship.
  5. Release starts at the exact dragged position and uses an overdamped spring with overshoot clamping to reach the nearest slot.
  6. Rows use absolute UI-thread slots keyed by item ID. The visual order and drag reset change together when the spring finishes; React receives the array afterward, so even a delayed render cannot move a row back to its old slot. Regrabbing the settling row cancels its spring and continues from its current position.

Install

npx expo install expo-image @shopify/react-native-skia react-native-gesture-handler react-native-reanimated react-native-worklets

Icons: Lucide (ISC).

Usage

import { LiftReorderList } from './lift-reorder-list';

const songs = [
  { id: 'one', title: 'Paper Moons', subtitle: 'Elio North', trailing: '3:42' },
  { id: 'two', title: 'Violet Hour', subtitle: 'June Arcade', trailing: '4:06' },
];

export function Queue() {
  return <LiftReorderList items={songs} onOrderChange={(next) => saveQueue(next)} />;
}
<LiftReorderList
  items={songs}
  rowHeight={68}
  rowGap={4}
  liftedColor="#211A29"
  accentColor="#F472B6"
  accessibilityLabel="Playback queue"
/>

Props

PropTypeDefaultDescription
itemsLiftReorderItem[]RequiredItems displayed in the reorderable list.
rowHeightnumber64Height of each row.
rowGapnumber2Gap between rows.
liftedColorstring'#1D1823'Background of a lifted row.
accentColorstring'#C084FC'Accent used for the release highlight.
textColorstring'#F7F2FA'Primary text color.
mutedColorstring'#9C92A5'Secondary text and grip color.
fontFamilystringundefinedTypeface for titles and subtitles.
mediumFontFamilystringundefinedMedium typeface for row titles.
monoFontFamilystringundefinedMonospaced typeface for trailing values.
onOrderChange(items: LiftReorderItem[]) => voidundefinedCalled after a move settles with the new item order.
accessibilityLabelstring'Reorderable list'Screen-reader label for the list.
styleStyleProp<ViewStyle>undefinedOptional style for the outer container.
testIDstringundefinedTest identifier applied to the outer container.
durationnumber820Programmatic reorder movement duration in milliseconds. Spring physics and reduced-motion timing are unchanged.

The ref exposes move(fromIndex, toIndex) and reset().

Compatibility

Built for Expo SDK 58, React Native 0.88, Reanimated 4.7, Worklets 0.13, and Skia 2.14. Supports iOS, Android, and web. Compatible with Expo Go because every native dependency is included in Expo Go for this SDK.

Accessibility

Each row is an adjustable element with labeled Move up and Move down actions. Hit areas are at least 44 points. Reduced Motion removes scale, tilt, and animated settling; released and programmatic moves update their slots immediately.

FAQ

How does dragging start and what happens near the edge?
A 300 ms hold starts a drag on the row; its grip starts immediately. Near an edge, auto-scroll advances the list while preserving the finger-to-row relationship. Release settles the row into its nearest slot.
How do I save or change the row order?
Use onOrderChange to persist the new item array after a move settles. The ref offers move(fromIndex, toIndex) and reset(). The component reorders its own rows; cross-list transfers are outside its documented API.
Can someone reorder without a drag gesture?
Each row is adjustable with labeled Move up and Move down actions and hit areas of at least 44 points. Reduced Motion removes lift, tilt, and animated settling, applying moves immediately.