Organism
ReorderableList
Requires <UIProvider> — Getting Started →
Installation
Install just this component (copies the source into your project, no npm dependency)
npx orn-ui add reorderable-listOr install the whole package and import it
pnpm add orn-ui
import { ReorderableList } from 'orn-ui/reorderable-list';Depends on:core (theme + icons)
Usage
- when to use — A short, fully-loaded list people rearrange by hand: playlists, priority lists, custom sort order.
- itemHeight — Required and fixed — the drop index is computed from drag distance, not from measuring layout.
- onReorder — Fires on release with the array already reordered; `data` itself is never mutated.
- disabled — Rows still render, dragging just stops responding — no separate read-only variant needed.
Demo clip not recorded yet — see MEDIA.md
Variants
Long-press a row and drag — the rows in between shift out of the way
<ReorderableList
data={data}
keyExtractor={(item) => item.id}
itemHeight={ITEM_HEIGHT}
onReorder={setData}
renderItem={(item, _index, dragging) => <Row name={item.name} dragging={dragging} />}
/>disabled — rows render but can’t be dragged
<ReorderableList
data={INITIAL}
keyExtractor={(item) => item.id}
itemHeight={ITEM_HEIGHT}
disabled
onReorder={() => {}}
renderItem={(item, _index, dragging) => <Row name={item.name} dragging={dragging} />}
/>Full demo source
const variants: VariantDef[] = [
{
label: 'Long-press a row and drag — the rows in between shift out of the way',
content: (
<ReorderableList
data={data}
keyExtractor={(item) => item.id}
itemHeight={ITEM_HEIGHT}
onReorder={setData}
renderItem={(item, _index, dragging) => <Row name={item.name} dragging={dragging} />}
/>
),
},
{
label: 'disabled — rows render but can’t be dragged',
content: (
<ReorderableList
data={INITIAL}
keyExtractor={(item) => item.id}
itemHeight={ITEM_HEIGHT}
disabled
onReorder={() => {}}
renderItem={(item, _index, dragging) => <Row name={item.name} dragging={dragging} />}
/>
),
},
];
return (
<>
<Caption style={{ marginBottom: 8 }}>Web preview doesn’t simulate touch drag — see the gif on this page.</Caption>
<VariantList variants={variants} />
</>
);Props
| Name | Type | Default | Description |
|---|---|---|---|
data | T[] | — | — |
keyExtractor | (item: T, index: number) => string | — | — |
itemHeight | number | — | Fixed height of each row: needed to calculate the target index without measuring layout async. |
renderItem | (item: T, index: number, dragging: boolean) => ReactElement<unknown, string | JSXElementConstructor<any>> | — | — |
onReorder | (data: T[]) => void | — | Called on release, with the array already reordered. Does not mutate `data`. |
onDragStart? | (index: number) => void | — | Starts dragging row `index`. Use it to turn off the container's scroll (`scrollEnabled={false}`) while it lasts: on iOS the parent `UIScrollView` cancels touches on the content as soon as its vertical gesture starts, and without this the drag dies within a few pixels. |
onDragEnd? | () => void | — | Ends the drag — on release or cancellation. Always runs if `onDragStart` ran. |
disabled? | boolean | false | — |
style? | StyleProp<ViewStyle> | — | — |