ComposeReorderable: drag and drop reordering for Jetpack Compose lists
Enables reordering by drag and drop in Jetpack Compose (Desktop) LazyList & LazyGrid.
At a glance
- What is it?
- ComposeReorderable is a Jetpack Compose modifier that enables drag and drop reordering in LazyList and LazyGrid on Android and Desktop. Its dependency coordinate is org.burnoutcrew.composereorderable:reorderable.
- Who is it for?
- Adopt ComposeReorderable if you build Jetpack Compose apps and need drag and drop reordering in LazyList or LazyGrid. Skip it if you target only Web or need guaranteed animation on the first visible item.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 157 days ago.
- What is it written in?
- Mainly Kotlin, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What ComposeReorderable adds to a Compose app
ComposeReorderable is a modifier that enables reordering by drag and drop in a LazyList and LazyGrid, for both Android and Desktop targets of Jetpack Compose. It does not replace the standard list components; instead it wraps them with a reorderable state and a modifier.
The intended user is a developer building a Compose UI who needs users to rearrange list or grid items by dragging. The project is licensed under Apache-2.0. The repository contains android, desktop, and web modules alongside the reorderable library, plus sample code. The README points to a sample app for different implementation samples.
How the reorderable state and modifiers work
The mechanism centers on a reorderable state object. You create one with rememberReorderableLazyListState for a LazyList or rememberReorderableLazyGridState for a LazyGrid, passing an onMove callback that mutates your backing data. You then add the reorderable(state) modifier to the list or grid, and create a ReorderableItem inside the item scope, keyed by key for keyed lists or indexed by index for indexed-only lists. Animated items only work with keyed lists.
Drag detection is opt-in through modifiers. Apply detectReorderAfterLongPress(state) or detectReorder(state) to the list, or apply the detect modifier to a child composable inside the item layout when only a drag handle is needed. ReorderableItem provides the item dragging state, which can drive elevation, scale, and other visual changes. The item placement and drag cancelled animation can be changed or disabled through dragCancelledAnimation and defaultDraggingModifier.
The README notes that it is a known issue that the first visible item does not animate. That is a concrete limitation to test against your own UI before adopting.
Installing ComposeReorderable
The README shows the dependency declaration for Gradle.
dependencies {
implementation("org.burnoutcrew.composereorderable:reorderable:<latest_version>")
}Replace <latest_version> with a version from the releases list. Recent releases are 0.9.6 on 2022-11-13, 0.9.4 on 2022-10-26, and 0.9.2 on 2022-06-16. The latest release badge points to the newest on GitHub.
The repository is built with Gradle, as shown by build.gradle.kts, settings.gradle.kts, gradlew, and gradle.properties. The top-level modules include android, desktop, web, and reorderable.
A minimal reorderable list in Compose
The README provides a vertical list example using LazyColumn.
@Composable
fun VerticalReorderList() {
val data = remember { mutableStateOf(List(100) { "Item $it" }) }
val state = rememberReorderableLazyListState(onMove = { from, to ->
data.value = data.value.toMutableList().apply {
add(to.index, removeAt(from.index))
}
})
LazyColumn(
state = state.listState,
modifier = Modifier
.reorderable(state)
.detectReorderAfterLongPress(state)
) {
items(data.value, { it }) { item ->
ReorderableItem(state, key = item) { isDragging ->
val elevation = animateDpAsState(if (isDragging) 16.dp else 0.dp)
Column(
modifier = Modifier
.shadow(elevation.value)
.background(MaterialTheme.colors.surface)
) {
Text(item)
}
}
}
}
}The onMove callback reorders the backing list by removing the item at from.index and inserting it at to.index. The isDragging flag drives the elevation animation. A grid variant uses rememberReorderableLazyGridState with LazyVerticalGrid and can disable the drag cancelled animation or change the default dragging modifier.
Grid reordering and animation controls
The vertical grid example uses rememberReorderableLazyGridState with dragCancelledAnimation set to NoDragCancelledAnimation, and sets defaultDraggingModifier to Modifier on the ReorderableItem. Items are placed in a LazyVerticalGrid with GridCells.Fixed(4). Drag detection is moved onto the child composable through Modifier.detectReorderAfterLongPress(state) inside the item content.
The two animation controls are dragCancelledAnimation, which can change or disable the cancel animation, and defaultDraggingModifier, which changes the dragging appearance. These let a developer tune how an item looks while being dragged and how it settles when the drag is cancelled.
Limitations and when ComposeReorderable is the wrong tool
The README states a known issue: the first visible item does not animate. Any UI that depends on smooth animation of the first item will need a workaround or a different library.
ComposeReorderable is the wrong tool if you target platforms outside Android and Desktop, since the README scopes support to those two, or if you need Web support without testing it yourself. It is also the wrong tool if you require a stable, frequently released library, because the latest release listed is 0.9.6 from 2022-11-13 while the last push was on 2026-05-19.
The README does not document rollback, versioning policy, or migration steps between releases.
Alternatives and how the approach differs
The README does not name a competing reordering library. The approach differs from building reordering manually in two ways. First, it separates state, modifier, and item scope, so the same backing data mutation works for both lists and grids. Second, it keeps drag detection configurable at the list level or at the item level, which lets a drag handle live inside an item rather than covering the whole row.
A manual implementation would give full control but would require reimplementing state tracking, index mapping, and animation. ComposeReorderable trades that control for a documented API with known animation limitations.
Maintenance, licensing and upgrade cost
The repository is not archived and the last push was on 2026-05-19. The latest release listed is 0.9.6 on 2022-11-13, with earlier releases 0.9.4 and 0.9.2. The license is Apache-2.0.
Upgrade cost is driven by Jetpack Compose and Kotlin version compatibility. The library depends on Compose APIs for LazyList and LazyGrid, so a Compose upgrade may require a matching library version. Because releases are sparse, a team should pin a version and verify it against its Compose BOM before upgrading.
The Apache-2.0 license allows use, modification, and distribution, including in commercial products, with attribution and patent provisions, but this is not legal advice and a team should have counsel review its obligations.
Editorial conclusion
Adopt ComposeReorderable if you build Jetpack Compose apps and need drag and drop reordering in LazyList or LazyGrid. Skip it if you target only Web or need guaranteed animation on the first visible item. Verify the latest version on GitHub releases and test reordering with your own item animations before shipping.
Frequently asked questions
How do I add ComposeReorderable to a Gradle project?
Add implementation("org.burnoutcrew.composereorderable:reorderable:<latest_version>") to your dependencies, replacing the version placeholder with a release version.
Does ComposeReorderable support LazyGrid?
Yes, it provides rememberReorderableLazyGridState and works with LazyVerticalGrid.
Why does the first item not animate in ComposeReorderable?
The README lists it as a known issue that the first visible item does not animate.
Can drag detection be limited to a handle in ComposeReorderable?
Yes, apply the detect modifier to a child composable inside the item layout instead of the whole list.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/aclassen-composereorderable)Was this useful?