{"id":14259548,"url":"https://github.com/Calvin-LL/Reorderable","last_synced_at":"2025-08-13T03:31:57.108Z","repository":{"id":208155153,"uuid":"720887699","full_name":"Calvin-LL/Reorderable","owner":"Calvin-LL","description":"Reorder items in Lists and Grids in Jetpack Compose and Compose Multiplatform with drag and drop.","archived":false,"fork":false,"pushed_at":"2025-08-12T23:36:52.000Z","size":18455,"stargazers_count":923,"open_issues_count":5,"forks_count":31,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-08-13T01:24:43.856Z","etag":null,"topics":["android","compose-multiplatform","drag-and-drop","draggable","grid","jetpack-compose","kotlin","list","reorderable","reorderable-list","reordering"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Calvin-LL.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-11-19T22:16:25.000Z","updated_at":"2025-08-12T23:36:55.000Z","dependencies_parsed_at":"2024-02-21T23:28:22.598Z","dependency_job_id":"312c390e-e600-445a-9da1-3f991a593095","html_url":"https://github.com/Calvin-LL/Reorderable","commit_stats":null,"previous_names":["calvin-ll/reorderable"],"tags_count":38,"template":false,"template_full_name":null,"purl":"pkg:github/Calvin-LL/Reorderable","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Calvin-LL%2FReorderable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Calvin-LL%2FReorderable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Calvin-LL%2FReorderable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Calvin-LL%2FReorderable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Calvin-LL","download_url":"https://codeload.github.com/Calvin-LL/Reorderable/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Calvin-LL%2FReorderable/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270175768,"owners_count":24540078,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-13T02:00:09.904Z","response_time":66,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","compose-multiplatform","drag-and-drop","draggable","grid","jetpack-compose","kotlin","list","reorderable","reorderable-list","reordering"],"created_at":"2024-08-22T10:01:22.645Z","updated_at":"2025-08-13T03:31:56.446Z","avatar_url":"https://github.com/Calvin-LL.png","language":"Kotlin","readme":"# Reorderable\n\nReorderable is a simple library that allows you to reorder items in [`LazyColumn`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyColumn(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), [`LazyRow`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyRow(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.ui.Alignment.Vertical,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), [`LazyVerticalGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/grid/package-summary#LazyVerticalGrid(androidx.compose.foundation.lazy.grid.GridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.grid.LazyGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), [`LazyHorizontalGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/grid/package-summary#LazyHorizontalGrid(androidx.compose.foundation.lazy.grid.GridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.grid.LazyGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), [`LazyVerticalStaggeredGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/staggeredgrid/package-summary#LazyVerticalStaggeredGrid(androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.ui.unit.Dp,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), and [`LazyHorizontalStaggeredGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/staggeredgrid/package-summary#LazyHorizontalStaggeredGrid(androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.unit.Dp,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e) as well as [`Column`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Column(androidx.compose.ui.Modifier,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,kotlin.Function1)\u003e) and [`Row`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Row(androidx.compose.ui.Modifier,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.ui.Alignment.Vertical,kotlin.Function1)\u003e) in Jetpack Compose and Compose Multiplatform with drag and drop.\n\nThe latest demo app APK can be found in the [releases](https://github.com/Calvin-LL/Reorderable/releases) section under the \"Assets\" section of the latest release.\n\n\u003ctable width=\"100%\" align=\"center\"\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\n      \u003cth width=\"50%\"\u003eLazyColumn\u003c/th\u003e\n      \u003cth width=\"50%\"\u003eLazyGrid\u003c/th\u003e\n    \u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd width=\"50%\"\u003e\n        \u003cimg\n          src=\"lazy-column-demo.webp\"\n          width=\"320\"\n          alt=\"A video showing an item being reordered in a LazyColumn\"\n        /\u003e\n      \u003c/td\u003e\n      \u003ctd width=\"50%\"\u003e\n        \u003cimg\n          src=\"lazy-grid-demo.webp\"\n          width=\"320\"\n          alt=\"A video showing an item being reordered in a LazyGrid\"\n        /\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n## Used By\n\n- [Lawnchair](https://github.com/LawnchairLauncher/lawnchair/blob/10889eb9772d5ec05f8ec536db3986ad5d9f4f33/build.gradle#L420) ![GitHub Repo stars](https://img.shields.io/github/stars/LawnchairLauncher/lawnchair?style=flat)\n- [Home Assistant](https://github.com/home-assistant/android/blob/b7281155f1bdc0bf53780e8b304cda1ae0532fd4/gradle/libs.versions.toml#L211) ![GitHub Repo stars](https://img.shields.io/github/stars/home-assistant/android?style=flat)\n- [ProtonVPN](https://github.com/ProtonVPN/android-app/blob/c1543ff1c299df376dac762d12e6049de95fdea8/app/build.gradle#L796) ![GitHub Repo stars](https://img.shields.io/github/stars/ProtonVPN/android-app?style=flat)\n- [Pocket Casts](https://github.com/Automattic/pocket-casts-android/blob/96cb6c6c3e210800a5fd2365776eee896079e255/gradle/libs.versions.toml#L281) ![GitHub Repo stars](https://img.shields.io/github/stars/Automattic/pocket-casts-android?style=flat)\n- [gkd](https://github.com/gkd-kit/gkd/blob/de140488aa42330d282cc41b92127237308e25f2/gradle/libs.versions.toml#L63) ![GitHub Repo stars](https://img.shields.io/github/stars/gkd-kit/gkd?style=flat)\n- [Mihon](https://github.com/mihonapp/mihon/blob/919607cd06ee45ac667a2fd650d85aaf6ebb9762/gradle/libs.versions.toml#L68) ![GitHub Repo stars](https://img.shields.io/github/stars/mihonapp/mihon?style=flat)\n- [AB Download Manager](https://github.com/amir1376/ab-download-manager/blob/dcf802b0583ab44fc806c86fc715fd2364d811db/gradle/libs.versions.toml#L100) ![GitHub Repo stars](https://img.shields.io/github/stars/amir1376/ab-download-manager?style=flat)\n- [ImageToolbox](https://github.com/T8RIN/ImageToolbox/blob/f03ba7e7dd497b215cc14cf80ee4991d42d101a4/gradle/libs.versions.toml#L160) ![GitHub Repo stars](https://img.shields.io/github/stars/T8RIN/ImageToolbox?style=flat)\n- [Aniyomi](https://github.com/aniyomiorg/aniyomi/blob/0697aad3204cf95547edcde1b98ca80c124d2677/gradle/libs.versions.toml#L67) ![GitHub Repo stars](https://img.shields.io/github/stars/aniyomiorg/aniyomi?style=flat)\n- [InnerTune](https://github.com/z-huang/InnerTune/blob/ba3a3a0fe9d3499205a7fc91649938091cad75b8/gradle/libs.versions.toml#L34) ![GitHub Repo stars](https://img.shields.io/github/stars/z-huang/InnerTune?style=flat)\n- [StreetComplete](https://github.com/streetcomplete/StreetComplete/blob/bcb8b58597c5e55b59b71be3568eed5e6a025e9b/app/build.gradle.kts#L154) ![GitHub Repo stars](https://img.shields.io/github/stars/streetcomplete/StreetComplete?style=flat)\n- [HeliBoard](https://github.com/Helium314/HeliBoard/blob/0787a79de4d118aa5efc7515cc3d5c84aa834951/app/build.gradle.kts#L122) ![GitHub Repo stars](https://img.shields.io/github/stars/Helium314/HeliBoard?style=flat)\n- [EhViewer](https://github.com/FooIbar/EhViewer/blob/4bb6b0baf69f4e996e1dd0bdb89a7f112819bf02/gradle/libs.versions.toml#L102) ![GitHub Repo stars](https://img.shields.io/github/stars/FooIbar/EhViewer?style=flat)\n- [bilimiao](https://github.com/10miaomiao/bilimiao2/blob/b806379206283309defd6d0ef9ad3b575dd46642/bilimiao-compose/build.gradle.kts#L83) ![GitHub Repo stars](https://img.shields.io/github/stars/10miaomiao/bilimiao2?style=flat)\n- [Twine](https://github.com/msasikanth/twine/blob/841defa05f03c13e56fd331e288f9a5e676862ca/gradle/libs.versions.toml#L124) ![GitHub Repo stars](https://img.shields.io/github/stars/msasikanth/twine?style=flat)\n- [Neo Launcher](https://github.com/NeoApplications/Neo-Launcher/blob/c3788690e31d13249ae70e9db628ed7e9baa86d4/gradle/libs.versions.toml#L112) ![GitHub Repo stars](https://img.shields.io/github/stars/NeoApplications/Neo-Launcher?style=flat)\n- [Komikku](https://github.com/komikku-app/komikku/blob/2661122d9ae532442526de136b25adb8045803ed/gradle/libs.versions.toml#L66) ![GitHub Repo stars](https://img.shields.io/github/stars/komikku-app/komikku?style=flat)\n- [Stream Chat](https://github.com/GetStream/stream-chat-android/blob/95a3f812991d7fe1e91d7457d125a039aeff704c/buildSrc/src/main/kotlin/io/getstream/chat/android/Dependencies.kt#L217) ![GitHub Repo stars](https://img.shields.io/github/stars/GetStream/stream-chat-android?style=flat)\n- [EinkBro](https://github.com/plateaukao/einkbro/blob/4dfa50fff1ced5035d1be77ef5af55ac165375e6/app/build.gradle.kts#L148) ![GitHub Repo stars](https://img.shields.io/github/stars/plateaukao/einkbro?style=flat)\n\n## Features\n\n- Supports Compose Multiplatform (Android, iOS, Desktop/JVM, Wasm, JS)\n- Supports items of different sizes\n- Some items can be made non-reorderable\n- Supports dragging and animating the first visible item\n- Supports dragging immediately or long press to start dragging\n- Supports section headers and footers\n- Scrolls when dragging to the edge of the screen. (unavailable for [`Column`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Column(androidx.compose.ui.Modifier,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,kotlin.Function1)\u003e) and [`Row`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Row(androidx.compose.ui.Modifier,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.ui.Alignment.Vertical,kotlin.Function1)\u003e)) The scroll speed is based on the distance from the edge of the screen.\n- Uses the new [`Modifier.animateItem`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/LazyItemScope#(androidx.compose.ui.Modifier).animateItem(androidx.compose.animation.core.FiniteAnimationSpec,androidx.compose.animation.core.FiniteAnimationSpec,androidx.compose.animation.core.FiniteAnimationSpec)\u003e) API to animate item movement in [`LazyColumn`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyColumn(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), [`LazyRow`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyRow(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.ui.Alignment.Vertical,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), [`LazyVerticalGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/grid/package-summary#LazyVerticalGrid(androidx.compose.foundation.lazy.grid.GridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.grid.LazyGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), [`LazyHorizontalGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/grid/package-summary#LazyHorizontalGrid(androidx.compose.foundation.lazy.grid.GridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.grid.LazyGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), [`LazyVerticalStaggeredGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/staggeredgrid/package-summary#LazyVerticalStaggeredGrid(androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.ui.unit.Dp,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), and [`LazyHorizontalStaggeredGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/staggeredgrid/package-summary#LazyHorizontalStaggeredGrid(androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.unit.Dp,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e)\n- Supports using a child of an item as the drag handle\n\n## Usage\n\n### Version Catalog\n\nIf you're using Version Catalog, add the following to your `libs.versions.toml` file:\n\n```toml\n[versions]\n#...\nreorderable = \"3.0.0\"\n\n[libraries]\n#...\nreorderable = { module = \"sh.calvin.reorderable:reorderable\", version.ref = \"reorderable\" }\n```\n\nor\n\n```toml\n[libraries]\n#...\nreorderable = { module = \"sh.calvin.reorderable:reorderable\", version = \"3.0.0\" }\n```\n\nthen\n\n```kotlin\ndependencies {\n    // ...\n    implementation(libs.reorderable)\n}\n```\n\n### Gradle\n\nIf you're using Gradle instead, add the following to your `build.gradle` file:\n\n#### Kotlin DSL\n\n```kotlin\ndependencies {\n    // ...\n    implementation(\"sh.calvin.reorderable:reorderable:3.0.0\")\n}\n```\n\n#### Groovy DSL\n\n```groovy\ndependencies {\n    // ...\n    implementation 'sh.calvin.reorderable:reorderable:3.0.0'\n}\n```\n\n### Examples\n\nSee [demo app code](demoApp/composeApp/src/commonMain/kotlin/sh/calvin/reorderable/demo) for more examples.\n\n#### Table of Contents\n\n- [`LazyColumn`](#lazycolumn)\n- [`LazyRow`](#lazyrow)\n- [`LazyVerticalGrid`](#lazyverticalgrid)\n- [`LazyHorizontalGrid`](#lazyhorizontalgrid)\n- [`LazyVerticalStaggeredGrid`](#lazyverticalstaggeredgrid)\n- [`LazyHorizontalStaggeredGrid`](#lazyhorizontalstaggeredgrid)\n- [`Column`](#column)\n- [`Row`](#row)\n- [Accessibility](#accessibility)\n- [FAQ](#faq)\n\n#### `LazyColumn`\n\nFind more examples in [`SimpleReorderableLazyColumnScreen.kt`](demoApp/composeApp/src/commonMain/kotlin/sh/calvin/reorderable/demo/ui/SimpleReorderableLazyColumnScreen.kt), [`SimpleLongPressHandleReorderableLazyColumnScreen.kt`](demoApp/composeApp/src/commonMain/kotlin/sh/calvin/reorderable/demo/ui/SimpleLongPressHandleReorderableLazyColumnScreen.kt) and [`ComplexReorderableLazyColumnScreen.kt`](demoApp/composeApp/src/commonMain/kotlin/sh/calvin/reorderable/demo/ui/ComplexReorderableLazyColumnScreen.kt) in the demo app.\n\n##### Simple Example\n\nTo use this library with [`LazyColumn`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyColumn(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), follow this basic structure:\n\n```kotlin\nval lazyListState = rememberLazyListState()\nval reorderableLazyListState = rememberReorderableLazyListState(lazyListState) { from, to -\u003e\n    // Update the list\n}\n\nLazyColumn(state = lazyListState) {\n    items(list, key = { /* item key */ }) {\n        ReorderableItem(reorderableLazyListState, key = /* item key */) { isDragging -\u003e\n            // Item content\n\n            IconButton(\n                modifier = Modifier.draggableHandle(),\n                /* ... */\n            )\n        }\n    }\n}\n\n```\n\n##### Complete Example (with haptic feedback)\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyListState = rememberLazyListState()\nval reorderableLazyListState = rememberReorderableLazyListState(lazyListState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        add(to.index, removeAt(from.index))\n    }\n\n    hapticFeedback.performHapticFeedback(HapticFeedbackType.SegmentFrequentTick)\n}\n\nLazyColumn(\n    modifier = Modifier.fillMaxSize(),\n    state = lazyListState,\n    contentPadding = PaddingValues(8.dp),\n    verticalArrangement = Arrangement.spacedBy(8.dp),\n) {\n    items(list, key = { it }) {\n        ReorderableItem(reorderableLazyListState, key = it) { isDragging -\u003e\n            val elevation by animateDpAsState(if (isDragging) 4.dp else 0.dp)\n\n            Surface(shadowElevation = elevation) {\n                Row {\n                    Text(it, Modifier.padding(horizontal = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureThresholdActivate)\n                            },\n                            onDragStopped = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureEnd)\n                            },\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n##### Section Headers and Footers or Multiple Lists\n\nThe `from.index` and `to.index` in `onMove` are the indices of the items in the `LazyColumn`. If you have section headers or footers, you may need to adjust the indices accordingly. For example:\n\n```kotlin\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyListState = rememberLazyListState()\nval reorderableLazyColumnState = rememberReorderableLazyListState(lazyListState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        add(to.index - 1, removeAt(from.index - 1))\n    }\n}\n\nLazyColumn(\n    state = lazyListState,\n    // ...\n) {\n    item {\n        Text(\"Header\")\n    }\n\n    items(list, key = { item -\u003e item.id }) { item -\u003e\n        ReorderableItem(reorderableLazyColumnState, item.id) {\n            // ...\n        }\n    }\n}\n```\n\n##### Passing `Modifier.draggableHandle` to a Child Composable\n\nSince `Modifier.draggableHandle` and `Modifier.longPressDraggableHandle` can only be used in `ReorderableCollectionItemScope`, you may need to pass `ReorderableCollectionItemScope` to a child composable. For example:\n\n```kotlin\n@Composable\nfun List() {\n    // ...\n\n    LazyColumn(state = lazyListState) {\n        items(list, key = { /* item key */ }) {\n            ReorderableItem(reorderableLazyListState, key = /* item key */) { isDragging -\u003e\n                // Item content\n\n                DragHandle(this)\n            }\n        }\n    }\n}\n\n@Composable\nfun DragHandle(scope: ReorderableCollectionItemScope) {\n    IconButton(\n        modifier = with(scope) {\n            Modifier.draggableHandle()\n        },\n        /* ... */\n    )\n}\n```\n\n##### Scroll Trigger Padding\n\nIf your [`LazyColumn`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyColumn(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e) displays under navigation bar or notification bar, you may want to add `scrollThresholdPadding` to `rememberReorderableLazyListState` to move the scroll trigger area out from under the navigation bar or notification bar.\n\n```kotlin\nval reorderableLazyListState = rememberReorderableLazyListState(\n    lazyListState = lazyListState,\n    scrollThresholdPadding = WindowInsets.systemBars.asPaddingValues(),\n) { from, to -\u003e\n    ...\n}\n```\n\n##### Use with [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e)\n\nIf you want to use the [material3's Clickable Card](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e), you can create a [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) and pass it to both the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) and the `Modifier.draggableHandle` (or `Modifier.longPressDraggableHandle`), `Modifier.draggableHandle` will emit drag events to the [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) so that the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) can respond to the drag events:\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyListState = rememberLazyListState()\nval reorderableLazyListState = rememberReorderableLazyListState(lazyListState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        add(to.index, removeAt(from.index))\n    }\n\n    hapticFeedback.performHapticFeedback(HapticFeedbackType.SegmentFrequentTick)\n}\n\nLazyColumn(\n    modifier = Modifier.fillMaxSize(),\n    state = lazyListState,\n    contentPadding = PaddingValues(8.dp),\n    verticalArrangement = Arrangement.spacedBy(8.dp),\n) {\n    items(list, key = { it }) { item -\u003e\n        ReorderableItem(reorderableLazyListState, key = item) {\n            val interactionSource = remember { MutableInteractionSource() }\n\n            Card(\n                onClick = {},\n                interactionSource = interactionSource,\n            ) {\n                Row {\n                    Text(item, Modifier.padding(horizontal = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureThresholdActivate)\n                            },\n                            onDragStopped = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureEnd)\n                            },\n                            interactionSource = interactionSource,\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n#### LazyRow\n\nSee [`SimpleReorderableLazyRowScreen.kt`](demoApp/composeApp/src/commonMain/kotlin/sh/calvin/reorderable/demo/ui/SimpleReorderableLazyRowScreen.kt) and [`ComplexReorderableLazyRowScreen.kt`](demoApp/composeApp/src/commonMain/kotlin/sh/calvin/reorderable/demo/ui/ComplexReorderableLazyRowScreen.kt) in the demo app.\n\n##### Simple Example\n\nTo use this library with [`LazyRow`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyRow(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.ui.Alignment.Vertical,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), follow this basic structure:\n\n```kotlin\nval lazyListState = rememberLazyListState()\nval reorderableLazyListState = rememberReorderableLazyListState(lazyListState) { from, to -\u003e\n    // Update the list\n}\n\nLazyRow(state = lazyListState) {\n    items(list, key = { /* item key */ }) {\n        ReorderableItem(reorderableLazyListState, key = /* item key */) { isDragging -\u003e\n            // Item content\n\n            IconButton(\n                modifier = Modifier.draggableHandle(),\n                /* ... */\n            )\n        }\n    }\n}\n\n```\n\n##### Complete Example (with haptic feedback)\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyListState = rememberLazyListState()\nval reorderableLazyListState = rememberReorderableLazyListState(lazyListState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        add(to.index, removeAt(from.index))\n    }\n\n    hapticFeedback.performHapticFeedback(HapticFeedbackType.SegmentFrequentTick)\n}\n\nLazyRow(\n    modifier = Modifier.fillMaxSize(),\n    state = lazyListState,\n    contentPadding = PaddingValues(8.dp),\n    horizontalArrangement = Arrangement.spacedBy(8.dp),\n) {\n    items(list, key = { it }) {\n        ReorderableItem(reorderableLazyListState, key = it) { isDragging -\u003e\n            val elevation by animateDpAsState(if (isDragging) 4.dp else 0.dp)\n\n            Surface(shadowElevation = elevation) {\n                Column {\n                    Text(it, Modifier.padding(vertical = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureThresholdActivate)\n                            },\n                            onDragStopped = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureEnd)\n                            },\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n##### Section Headers and Footers or Multiple Lists\n\nThe `from.index` and `to.index` in `onMove` are the indices of the items in the `LazyRow`. If you have section headers or footers, you may need to adjust the indices accordingly. For example:\n\n```kotlin\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyListState = rememberLazyListState()\nval reorderableLazyRowState = rememberReorderableLazyListState(lazyListState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        add(to.index - 1, removeAt(from.index - 1))\n    }\n}\n\nLazyRow(\n    state = lazyListState,\n    // ...\n) {\n    item {\n        Text(\"Header\")\n    }\n\n    items(list, key = { item -\u003e item.id }) { item -\u003e\n        ReorderableItem(reorderableLazyRowState, item.id) {\n            // ...\n        }\n    }\n}\n```\n\n##### Passing `Modifier.draggableHandle` to a Child Composable\n\nSince `Modifier.draggableHandle` and `Modifier.longPressDraggableHandle` can only be used in `ReorderableCollectionItemScope`, you may need to pass `ReorderableCollectionItemScope` to a child composable. For example:\n\n```kotlin\n@Composable\nfun List() {\n    // ...\n\n    LazyRow(state = lazyListState) {\n        items(list, key = { /* item key */ }) {\n            ReorderableItem(reorderableLazyListState, key = /* item key */) { isDragging -\u003e\n                // Item content\n\n                DragHandle(this)\n            }\n        }\n    }\n}\n\n@Composable\nfun DragHandle(scope: ReorderableCollectionItemScope) {\n    IconButton(\n        modifier = with(scope) {\n            Modifier.draggableHandle()\n        },\n        /* ... */\n    )\n}\n```\n\n##### Scroll Trigger Padding\n\nIf your [`LazyRow`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyRow(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.ui.Alignment.Vertical,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e) displays under navigation bar or notification bar, you may want to add `scrollThresholdPadding` to `rememberReorderableLazyListState` to move the scroll trigger area out from under the navigation bar or notification bar.\n\n```kotlin\nval reorderableLazyListState = rememberReorderableLazyListState(\n    lazyListState = lazyListState,\n    scrollThresholdPadding = WindowInsets.systemBars.asPaddingValues(),\n) { from, to -\u003e\n    ...\n}\n```\n\n##### Use with [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e)\n\nIf you want to use the [material3's Clickable Card](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e), you can create a [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) and pass it to both the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) and the `Modifier.draggableHandle` (or `Modifier.longPressDraggableHandle`), `Modifier.draggableHandle` will emit drag events to the [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) so that the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) can respond to the drag events:\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyListState = rememberLazyListState()\nval reorderableLazyListState = rememberReorderableLazyListState(lazyListState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        add(to.index, removeAt(from.index))\n    }\n\n    hapticFeedback.performHapticFeedback(HapticFeedbackType.SegmentFrequentTick)\n}\n\nLazyRow(\n    modifier = Modifier.fillMaxSize(),\n    state = lazyListState,\n    contentPadding = PaddingValues(8.dp),\n    horizontalArrangement = Arrangement.spacedBy(8.dp),\n) {\n    items(list, key = { it }) { item -\u003e\n        ReorderableItem(reorderableLazyListState, key = item) {\n            val interactionSource = remember { MutableInteractionSource() }\n\n            Card(\n                onClick = {},\n                interactionSource = interactionSource,\n            ) {\n                Column {\n                    Text(item, Modifier.padding(vertical = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureThresholdActivate)\n                            },\n                            onDragStopped = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureEnd)\n                            },\n                            interactionSource = interactionSource,\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n#### `LazyVerticalGrid`\n\nFind more examples in [`SimpleReorderableLazyVerticalGridScreen.kt`](demoApp/composeApp/src/commonMain/kotlin/sh/calvin/reorderable/demo/ui/SimpleReorderableLazyVerticalGridScreen.kt) in the demo app.\n\n##### Simple Example\n\nTo use this library with [`LazyVerticalGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/grid/package-summary#LazyVerticalGrid(androidx.compose.foundation.lazy.grid.GridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.grid.LazyGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), follow this basic structure:\n\n```kotlin\nval lazyGridState = rememberLazyGridState()\nval reorderableLazyGridState = rememberReorderableLazyGridState(lazyGridState) { from, to -\u003e\n    // Update the list\n}\n\nLazyVerticalGrid(state = lazyGridState) {\n    items(list, key = { /* item key */ }) {\n        ReorderableItem(reorderableLazyGridState, key = /* item key */) { isDragging -\u003e\n            // Item content\n\n            IconButton(\n                modifier = Modifier.draggableHandle(),\n                /* ... */\n            )\n        }\n    }\n}\n\n```\n\n##### Complete Example (with haptic feedback)\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyGridState = rememberLazyGridState()\nval reorderableLazyGridState = rememberReorderableLazyGridState(lazyGridState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        this[to.index] = this[from.index].also {\n            this[from.index] = this[to.index]\n        }\n    }\n\n    hapticFeedback.performHapticFeedback(HapticFeedbackType.SegmentFrequentTick)\n}\n\nLazyVerticalGrid(\n    columns = GridCells.Adaptive(minSize = 96.dp),\n    modifier = Modifier.fillMaxSize(),\n    state = lazyGridState,\n    contentPadding = PaddingValues(8.dp),\n    verticalArrangement = Arrangement.spacedBy(8.dp),\n    horizontalArrangement = Arrangement.spacedBy(8.dp),\n) {\n    items(list, key = { it }) {\n        ReorderableItem(reorderableLazyGridState, key = it) { isDragging -\u003e\n            val elevation by animateDpAsState(if (isDragging) 4.dp else 0.dp)\n\n            Surface(shadowElevation = elevation) {\n                Row {\n                    Text(it, Modifier.padding(horizontal = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureThresholdActivate)\n                            },\n                            onDragStopped = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureEnd)\n                            },\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n##### Section Headers and Footers or Multiple Lists\n\nThe `from.index` and `to.index` in `onMove` are the indices of the items in the `LazyVerticalGrid`. If you have section headers or footers, you may need to adjust the indices accordingly. For example:\n\n```kotlin\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyGridState = rememberLazyGridState()\nval reorderableLazyGridState = rememberReorderableLazyGridState(lazyGridState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        add(to.index - 1, removeAt(from.index - 1))\n    }\n}\n\nLazyVerticalGrid(\n    state = lazyGridState,\n    // ...\n) {\n    item {\n        Text(\"Header\")\n    }\n\n    items(list, key = { item -\u003e item.id }) { item -\u003e\n        ReorderableItem(reorderableLazyGridState, item.id) {\n            // ...\n        }\n    }\n}\n```\n\n##### Passing `Modifier.draggableHandle` to a Child Composable\n\nSince `Modifier.draggableHandle` and `Modifier.longPressDraggableHandle` can only be used in `ReorderableCollectionItemScope`, you may need to pass `ReorderableCollectionItemScope` to a child composable. For example:\n\n```kotlin\n@Composable\nfun Grid() {\n    // ...\n\n    LazyVerticalGrid(state = lazyGridState) {\n        items(Grid, key = { /* item key */ }) {\n            ReorderableItem(reorderableLazyGridState, key = /* item key */) { isDragging -\u003e\n                // Item content\n\n                DragHandle(this)\n            }\n        }\n    }\n}\n\n@Composable\nfun DragHandle(scope: ReorderableCollectionItemScope) {\n    IconButton(\n        modifier = with(scope) {\n            Modifier.draggableHandle()\n        },\n        /* ... */\n    )\n}\n```\n\n##### Scroll Trigger Padding\n\nIf your [`LazyVerticalGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/grid/package-summary#LazyVerticalGrid(androidx.compose.foundation.lazy.grid.GridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.grid.LazyGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e) displays under navigation bar or notification bar, you may want to add `scrollThresholdPadding` to `rememberReorderableLazyGridState` to move the scroll trigger area out from under the navigation bar or notification bar.\n\n```kotlin\nval reorderableLazyGridState = rememberReorderableLazyGridState(\n    lazyGridState = lazyGridState,\n    scrollThresholdPadding = WindowInsets.systemBars.asPaddingValues(),\n) { from, to -\u003e\n    ...\n}\n```\n\n##### Use with [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e)\n\nIf you want to use the [material3's Clickable Card](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e), you can create a [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) and pass it to both the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) and the `Modifier.draggableHandle` (or `Modifier.longPressDraggableHandle`), `Modifier.draggableHandle` will emit drag events to the [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) so that the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) can respond to the drag events:\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyGridState = rememberLazyGridState()\nval reorderableLazyGridState = rememberReorderableLazyGridState(lazyGridState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        this[to.index] = this[from.index].also {\n            this[from.index] = this[to.index]\n        }\n    }\n\n    hapticFeedback.performHapticFeedback(HapticFeedbackType.SegmentFrequentTick)\n}\n\nLazyVerticalGrid(\n    columns = GridCells.Adaptive(minSize = 96.dp),\n    modifier = Modifier.fillMaxSize(),\n    state = lazyGridState,\n    contentPadding = PaddingValues(8.dp),\n    verticalArrangement = Arrangement.spacedBy(8.dp),\n    horizontalArrangement = Arrangement.spacedBy(8.dp),\n) {\n    items(list, key = { it }) { item -\u003e\n        ReorderableItem(reorderableLazyGridState, key = item) {\n            val interactionSource = remember { MutableInteractionSource() }\n\n            Card(\n                onClick = {},\n                interactionSource = interactionSource,\n            ) {\n                Row {\n                    Text(item, Modifier.padding(horizontal = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureThresholdActivate)\n                            },\n                            onDragStopped = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureEnd)\n                            },\n                            interactionSource = interactionSource,\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n#### `LazyHorizontalGrid`\n\nFind more examples in [`SimpleReorderableLazyHorizontalGridScreen.kt`](demoApp/composeApp/src/commonMain/kotlin/sh/calvin/reorderable/demo/ui/SimpleReorderableLazyHorizontalGridScreen.kt) in the demo app.\n\n##### Simple Example\n\nTo use this library with [`LazyHorizontalGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/grid/package-summary#LazyHorizontalGrid(androidx.compose.foundation.lazy.grid.GridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.grid.LazyStaggeredGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), follow this basic structure:\n\n```kotlin\nval lazyGridState = rememberLazyGridState()\nval reorderableLazyGridState = rememberReorderableLazyGridState(lazyGridState) { from, to -\u003e\n    // Update the list\n}\n\nLazyHorizontalGrid(state = lazyGridState) {\n    items(list, key = { /* item key */ }) {\n        ReorderableItem(reorderableLazyGridState, key = /* item key */) { isDragging -\u003e\n            // Item content\n\n            IconButton(\n                modifier = Modifier.draggableHandle(),\n                /* ... */\n            )\n        }\n    }\n}\n\n```\n\n##### Complete Example (with haptic feedback)\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyGridState = rememberLazyGridState()\nval reorderableLazyGridState = rememberReorderableLazyGridState(lazyGridState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        this[to.index] = this[from.index].also {\n            this[from.index] = this[to.index]\n        }\n    }\n\n    hapticFeedback.performHapticFeedback(HapticFeedbackType.SegmentFrequentTick)\n}\n\nLazyHorizontalGrid(\n    rows = GridCells.Adaptive(minSize = 96.dp),\n    modifier = Modifier.fillMaxSize(),\n    state = lazyGridState,\n    contentPadding = PaddingValues(8.dp),\n    verticalArrangement = Arrangement.spacedBy(8.dp),\n    horizontalArrangement = Arrangement.spacedBy(8.dp),\n) {\n    items(list, key = { it }) {\n        ReorderableItem(reorderableLazyGridState, key = it) { isDragging -\u003e\n            val elevation by animateDpAsState(if (isDragging) 4.dp else 0.dp)\n\n            Surface(shadowElevation = elevation) {\n                Row {\n                    Text(it, Modifier.padding(horizontal = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureThresholdActivate)\n                            },\n                            onDragStopped = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureEnd)\n                            },\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n##### Section Headers and Footers or Multiple Lists\n\nThe `from.index` and `to.index` in `onMove` are the indices of the items in the `LazyHorizontalGrid`. If you have section headers or footers, you may need to adjust the indices accordingly. For example:\n\n```kotlin\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyGridState = rememberLazyGridState()\nval reorderableLazyGridState = rememberReorderableLazyGridState(lazyGridState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        add(to.index - 1, removeAt(from.index - 1))\n    }\n}\n\nLazyHorizontalGrid(\n    state = lazyGridState,\n    // ...\n) {\n    item {\n        Text(\"Header\")\n    }\n\n    items(list, key = { item -\u003e item.id }) { item -\u003e\n        ReorderableItem(reorderableLazyGridState, item.id) {\n            // ...\n        }\n    }\n}\n```\n\n##### Passing `Modifier.draggableHandle` to a Child Composable\n\nSince `Modifier.draggableHandle` and `Modifier.longPressDraggableHandle` can only be used in `ReorderableCollectionItemScope`, you may need to pass `ReorderableCollectionItemScope` to a child composable. For example:\n\n```kotlin\n@Composable\nfun Grid() {\n    // ...\n\n    LazyHorizontalGrid(state = lazyGridState) {\n        items(Grid, key = { /* item key */ }) {\n            ReorderableItem(reorderableLazyGridState, key = /* item key */) { isDragging -\u003e\n                // Item content\n\n                DragHandle(this)\n            }\n        }\n    }\n}\n\n@Composable\nfun DragHandle(scope: ReorderableCollectionItemScope) {\n    IconButton(\n        modifier = with(scope) {\n            Modifier.draggableHandle()\n        },\n        /* ... */\n    )\n}\n```\n\n##### Scroll Trigger Padding\n\nIf your [`LazyHorizontalGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/grid/package-summary#LazyHorizontalGrid(androidx.compose.foundation.lazy.grid.GridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.grid.LazyStaggeredGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e) displays under navigation bar or notification bar, you may want to add `scrollThresholdPadding` to `rememberReorderableLazyGridState` to move the scroll trigger area out from under the navigation bar or notification bar.\n\n```kotlin\nval reorderableLazyGridState = rememberReorderableLazyGridState(\n    lazyGridState = lazyGridState,\n    scrollThresholdPadding = WindowInsets.systemBars.asPaddingValues(),\n) { from, to -\u003e\n    ...\n}\n```\n\n##### Use with [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e)\n\nIf you want to use the [material3's Clickable Card](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e), you can create a [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) and pass it to both the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) and the `Modifier.draggableHandle` (or `Modifier.longPressDraggableHandle`), `Modifier.draggableHandle` will emit drag events to the [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) so that the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) can respond to the drag events:\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyGridState = rememberLazyGridState()\nval reorderableLazyGridState = rememberReorderableLazyGridState(lazyGridState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        this[to.index] = this[from.index].also {\n            this[from.index] = this[to.index]\n        }\n    }\n\n    hapticFeedback.performHapticFeedback(HapticFeedbackType.SegmentFrequentTick)\n}\n\nLazyHorizontalGrid(\n    rows = GridCells.Adaptive(minSize = 96.dp),\n    modifier = Modifier.fillMaxSize(),\n    state = lazyGridState,\n    contentPadding = PaddingValues(8.dp),\n    verticalArrangement = Arrangement.spacedBy(8.dp),\n    horizontalArrangement = Arrangement.spacedBy(8.dp),\n) {\n    items(list, key = { it }) { item -\u003e\n        ReorderableItem(reorderableLazyGridState, key = item) {\n            val interactionSource = remember { MutableInteractionSource() }\n\n            Card(\n                onClick = {},\n                interactionSource = interactionSource,\n            ) {\n                Row {\n                    Text(item, Modifier.padding(horizontal = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureThresholdActivate)\n                            },\n                            onDragStopped = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureEnd)\n                            },\n                            interactionSource = interactionSource,\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n#### `LazyVerticalStaggeredGrid`\n\nFind more examples in [`SimpleReorderableLazyVerticalStaggeredGridScreen.kt`](demoApp/composeApp/src/commonMain/kotlin/sh/calvin/reorderable/demo/ui/SimpleReorderableLazyVerticalStaggeredGridScreen.kt) in the demo app.\n\n##### Simple Example\n\nTo use this library with [`LazyVerticalStaggeredGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/staggeredgrid/package-summary#LazyVerticalStaggeredGrid(androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.ui.unit.Dp,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), follow this basic structure:\n\n```kotlin\nval lazyStaggeredGridState = rememberLazyStaggeredGridState()\nval reorderableLazyStaggeredGridState = rememberReorderableLazyStaggeredGridState(lazyStaggeredGridState) { from, to -\u003e\n    // Update the list\n}\n\nLazyVerticalStaggeredGrid(state = lazyStaggeredGridState) {\n    items(list, key = { /* item key */ }) {\n        ReorderableItem(reorderableLazyStaggeredGridState, key = /* item key */) { isDragging -\u003e\n            // Item content\n\n            IconButton(\n                modifier = Modifier.draggableHandle(),\n                /* ... */\n            )\n        }\n    }\n}\n\n```\n\n##### Complete Example (with haptic feedback)\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyStaggeredGridState = rememberLazyStaggeredGridState()\nval reorderableLazyStaggeredGridState = rememberReorderableLazyStaggeredGridState(lazyStaggeredGridState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        this[to.index] = this[from.index].also {\n            this[from.index] = this[to.index]\n        }\n    }\n\n    hapticFeedback.performHapticFeedback(HapticFeedbackType.SegmentFrequentTick)\n}\n\nLazyVerticalStaggeredGrid(\n    columns = StaggeredGridCells.Adaptive(minSize = 96.dp),\n    modifier = Modifier.fillMaxSize(),\n    state = lazyStaggeredGridState,\n    contentPadding = PaddingValues(8.dp),\n    verticalItemSpacing = 8.dp,\n    horizontalArrangement = Arrangement.spacedBy(8.dp),\n) {\n    items(list, key = { it }) {\n        ReorderableItem(reorderableLazyStaggeredGridState, key = it) { isDragging -\u003e\n            val elevation by animateDpAsState(if (isDragging) 4.dp else 0.dp)\n\n            Surface(shadowElevation = elevation) {\n                Row {\n                    Text(it, Modifier.padding(horizontal = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureThresholdActivate)\n                            },\n                            onDragStopped = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureEnd)\n                            },\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n##### Section Headers and Footers or Multiple Lists\n\nThe `from.index` and `to.index` in `onMove` are the indices of the items in the `LazyVerticalStaggeredGrid`. If you have section headers or footers, you may need to adjust the indices accordingly. For example:\n\n```kotlin\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyStaggeredGridState = rememberLazyStaggeredGridState()\nval reorderableLazyStaggeredGridState = rememberReorderableLazyStaggeredGridState(lazyStaggeredGridState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        add(to.index - 1, removeAt(from.index - 1))\n    }\n}\n\nLazyVerticalStaggeredGrid(\n    state = lazyStaggeredGridState,\n    // ...\n) {\n    item {\n        Text(\"Header\")\n    }\n\n    items(list, key = { item -\u003e item.id }) { item -\u003e\n        ReorderableItem(reorderableLazyStaggeredGridState, item.id) {\n            // ...\n        }\n    }\n}\n```\n\n##### Passing `Modifier.draggableHandle` to a Child Composable\n\nSince `Modifier.draggableHandle` and `Modifier.longPressDraggableHandle` can only be used in `ReorderableCollectionItemScope`, you may need to pass `ReorderableCollectionItemScope` to a child composable. For example:\n\n```kotlin\n@Composable\nfun Grid() {\n    // ...\n\n    LazyVerticalStaggeredGrid(state = lazyStaggeredGridState) {\n        items(list, key = { /* item key */ }) {\n            ReorderableItem(reorderableLazyStaggeredGridState, key = /* item key */) { isDragging -\u003e\n                // Item content\n\n                DragHandle(this)\n            }\n        }\n    }\n}\n\n@Composable\nfun DragHandle(scope: ReorderableCollectionItemScope) {\n    IconButton(\n        modifier = with(scope) {\n            Modifier.draggableHandle()\n        },\n        /* ... */\n    )\n}\n```\n\n##### Scroll Trigger Padding\n\nIf your [`LazyVerticalStaggeredGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/staggeredgrid/package-summary#LazyVerticalStaggeredGrid(androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.ui.unit.Dp,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e) displays under navigation bar or notification bar, you may want to add `scrollThresholdPadding` to `rememberReorderableLazyStaggeredGridState` to move the scroll trigger area out from under the navigation bar or notification bar.\n\n```kotlin\nval reorderableLazyStaggeredGridState = rememberReorderableLazyStaggeredGridState(\n    lazyStaggeredGridState = lazyStaggeredGridState,\n    scrollThresholdPadding = WindowInsets.systemBars.asPaddingValues(),\n) { from, to -\u003e\n    ...\n}\n```\n\n##### Use with [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e)\n\nIf you want to use the [material3's Clickable Card](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e), you can create a [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) and pass it to both the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) and the `Modifier.draggableHandle` (or `Modifier.longPressDraggableHandle`), `Modifier.draggableHandle` will emit drag events to the [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) so that the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) can respond to the drag events:\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyStaggeredGridState = rememberLazyStaggeredGridState()\nval reorderableLazyStaggeredGridState = rememberReorderableLazyStaggeredGridState(lazyStaggeredGridState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        this[to.index] = this[from.index].also {\n            this[from.index] = this[to.index]\n        }\n    }\n\n    hapticFeedback.performHapticFeedback(HapticFeedbackType.SegmentFrequentTick)\n}\n\nLazyVerticalStaggeredGrid(\n    columns = StaggeredGridCells.Adaptive(minSize = 96.dp),\n    modifier = Modifier.fillMaxSize(),\n    state = lazyStaggeredGridState,\n    contentPadding = PaddingValues(8.dp),\n    verticalItemSpacing = 8.dp,\n    horizontalArrangement = Arrangement.spacedBy(8.dp),\n) {\n    items(list, key = { it }) { item -\u003e\n        ReorderableItem(reorderableLazyStaggeredGridState, key = item) {\n            val interactionSource = remember { MutableInteractionSource() }\n\n            Card(\n                onClick = {},\n                interactionSource = interactionSource,\n            ) {\n                Row {\n                    Text(item, Modifier.padding(horizontal = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureThresholdActivate)\n                            },\n                            onDragStopped = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureEnd)\n                            },\n                            interactionSource = interactionSource,\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n#### `LazyHorizontalStaggeredGrid`\n\nFind more examples in [`SimpleReorderableLazyHorizontalStaggeredGridScreen.kt`](demoApp/composeApp/src/commonMain/kotlin/sh/calvin/reorderable/demo/ui/SimpleReorderableLazyHorizontalStaggeredGridScreen.kt) in the demo app.\n\n##### Simple Example\n\nTo use this library with [`LazyHorizontalStaggeredGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/staggeredgrid/package-summary#LazyHorizontalStaggeredGrid(androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.unit.Dp,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e), follow this basic structure:\n\n```kotlin\nval lazyStaggeredGridState = rememberLazyStaggeredGridState()\nval reorderableLazyStaggeredGridState = rememberReorderableLazyStaggeredGridState(lazyStaggeredGridState) { from, to -\u003e\n    // Update the list\n}\n\nLazyHorizontalStaggeredGrid(state = lazyStaggeredGridState) {\n    items(list, key = { /* item key */ }) {\n        ReorderableItem(reorderableLazyStaggeredGridState, key = /* item key */) { isDragging -\u003e\n            // Item content\n\n            IconButton(\n                modifier = Modifier.draggableHandle(),\n                /* ... */\n            )\n        }\n    }\n}\n\n```\n\n##### Complete Example (with haptic feedback)\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyStaggeredGridState = rememberLazyStaggeredGridState()\nval reorderableLazyStaggeredGridState = rememberReorderableLazyStaggeredGridState(lazyStaggeredGridState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        this[to.index] = this[from.index].also {\n            this[from.index] = this[to.index]\n        }\n    }\n\n    hapticFeedback.performHapticFeedback(HapticFeedbackType.SegmentFrequentTick)\n}\n\nLazyHorizontalStaggeredGrid(\n    rows = StaggeredGridCells.Adaptive(minSize = 96.dp),\n    modifier = Modifier.fillMaxSize(),\n    state = lazyStaggeredGridState,\n    contentPadding = PaddingValues(8.dp),\n    verticalArrangement = Arrangement.spacedBy(8.dp),\n    horizontalItemSpacing = 8.dp,\n) {\n    items(list, key = { it }) {\n        ReorderableItem(reorderableLazyStaggeredGridState, key = it) { isDragging -\u003e\n            val elevation by animateDpAsState(if (isDragging) 4.dp else 0.dp)\n\n            Surface(shadowElevation = elevation) {\n                Row {\n                    Text(it, Modifier.padding(horizontal = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureThresholdActivate)\n                            },\n                            onDragStopped = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureEnd)\n                            },\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n##### Section Headers and Footers or Multiple Lists\n\nThe `from.index` and `to.index` in `onMove` are the indices of the items in the `LazyHorizontalStaggeredGrid`. If you have section headers or footers, you may need to adjust the indices accordingly. For example:\n\n```kotlin\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyStaggeredGridState = rememberLazyStaggeredGridState()\nval reorderableLazyStaggeredGridState = rememberReorderableLazyStaggeredGridState(lazyStaggeredGridState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        add(to.index - 1, removeAt(from.index - 1))\n    }\n}\n\nLazyHorizontalStaggeredGrid(\n    state = lazyStaggeredGridState,\n    // ...\n) {\n    item {\n        Text(\"Header\")\n    }\n\n    items(list, key = { item -\u003e item.id }) { item -\u003e\n        ReorderableItem(reorderableLazyStaggeredGridState, item.id) {\n            // ...\n        }\n    }\n}\n```\n\n##### Passing `Modifier.draggableHandle` to a Child Composable\n\nSince `Modifier.draggableHandle` and `Modifier.longPressDraggableHandle` can only be used in `ReorderableCollectionItemScope`, you may need to pass `ReorderableCollectionItemScope` to a child composable. For example:\n\n```kotlin\n@Composable\nfun Grid() {\n    // ...\n\n    LazyHorizontalStaggeredGrid(state = lazyStaggeredGridState) {\n        items(list, key = { /* item key */ }) {\n            ReorderableItem(reorderableLazyStaggeredGridState, key = /* item key */) { isDragging -\u003e\n                // Item content\n\n                DragHandle(this)\n            }\n        }\n    }\n}\n\n@Composable\nfun DragHandle(scope: ReorderableCollectionItemScope) {\n    IconButton(\n        modifier = with(scope) {\n            Modifier.draggableHandle()\n        },\n        /* ... */\n    )\n}\n```\n\n##### Scroll Trigger Padding\n\nIf your [`LazyHorizontalStaggeredGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/staggeredgrid/package-summary#LazyHorizontalStaggeredGrid(androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.unit.Dp,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e) displays under navigation bar or notification bar, you may want to add `scrollThresholdPadding` to `rememberReorderableLazyStaggeredGridState` to move the scroll trigger area out from under the navigation bar or notification bar.\n\n```kotlin\nval reorderableLazyStaggeredGridState = rememberReorderableLazyStaggeredGridState(\n    lazyStaggeredGridState = lazyStaggeredGridState,\n    scrollThresholdPadding = WindowInsets.systemBars.asPaddingValues(),\n) { from, to -\u003e\n    ...\n}\n```\n\n##### Use with [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e)\n\nIf you want to use the [material3's Clickable Card](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e), you can create a [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) and pass it to both the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) and the `Modifier.draggableHandle` (or `Modifier.longPressDraggableHandle`), `Modifier.draggableHandle` will emit drag events to the [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) so that the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) can respond to the drag events:\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(100) { \"Item $it\" }) }\nval lazyStaggeredGridState = rememberLazyStaggeredGridState()\nval reorderableLazyStaggeredGridState = rememberReorderableLazyStaggeredGridState(lazyStaggeredGridState) { from, to -\u003e\n    list = list.toMutableList().apply {\n        this[to.index] = this[from.index].also {\n            this[from.index] = this[to.index]\n        }\n    }\n\n    hapticFeedback.performHapticFeedback(HapticFeedbackType.SegmentFrequentTick)\n}\n\nLazyHorizontalStaggeredGrid(\n    rows = StaggeredGridCells.Adaptive(minSize = 96.dp),\n    modifier = Modifier.fillMaxSize(),\n    state = lazyStaggeredGridState,\n    contentPadding = PaddingValues(8.dp),\n    verticalArrangement = Arrangement.spacedBy(8.dp),\n    horizontalItemSpacing = 8.dp,\n) {\n    items(list, key = { it }) { item -\u003e\n        ReorderableItem(reorderableLazyStaggeredGridState, key = item) {\n            val interactionSource = remember { MutableInteractionSource() }\n\n            Card(\n                onClick = {},\n                interactionSource = interactionSource,\n            ) {\n                Row {\n                    Text(item, Modifier.padding(horizontal = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureThresholdActivate)\n                            },\n                            onDragStopped = {\n                                hapticFeedback.performHapticFeedback(HapticFeedbackType.GestureEnd)\n                            },\n                            interactionSource = interactionSource,\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n#### `Column`\n\nFind more examples in [`ReorderableColumnScreen.kt`](demoApp/composeApp/src/commonMain/kotlin/sh/calvin/reorderable/demo/ui/ReorderableColumnScreen.kt) and [`LongPressHandleReorderableColumnScreen.kt`](demoApp/composeApp/src/commonMain/kotlin/sh/calvin/reorderable/demo/ui/LongPressHandleReorderableColumnScreen.kt) in the demo app.\n\n##### Simple Example\n\nTo use this library with [`Column`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Column(androidx.compose.ui.Modifier,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,kotlin.Function1)\u003e), follow this basic structure:\n\n```kotlin\nReorderableColumn(\n    list = list,\n    onSettle = { fromIndex, toIndex -\u003e\n        // Update the list\n    },\n) { index, item, isDragging -\u003e\n    key(item.id) {\n        ReorderableItem {\n            // Item content\n\n            IconButton(modifier = Modifier.draggableHandle(), /* ... */)\n        }\n    }\n}\n```\n\n##### Complete Example (with haptic feedback)\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(4) { \"Item $it\" }) }\n\nReorderableColumn(\n    modifier = Modifier\n        .fillMaxSize()\n        .padding(8.dp),\n    list = list,\n    onSettle = { fromIndex, toIndex -\u003e\n        list = list.toMutableList().apply {\n            add(toIndex, removeAt(fromIndex))\n        }\n    },\n    onMove = {\n        ViewCompat.performHapticFeedback(\n            view,\n            HapticFeedbackConstantsCompat.SEGMENT_FREQUENT_TICK\n        )\n    },\n    verticalArrangement = Arrangement.spacedBy(8.dp),\n) { _, item, isDragging -\u003e\n    key(item) {\n        ReorderableItem {\n            val elevation by animateDpAsState(if (isDragging) 4.dp else 0.dp)\n\n            Surface(shadowElevation = elevation) {\n                Row {\n                    Text(item, Modifier.padding(horizontal = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                ViewCompat.performHapticFeedback(\n                                    view,\n                                    HapticFeedbackConstantsCompat.GESTURE_START\n                                )\n                            },\n                            onDragStopped = {\n                                ViewCompat.performHapticFeedback(\n                                    view,\n                                    HapticFeedbackConstantsCompat.GESTURE_END\n                                )\n                            },\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n##### Passing `Modifier.draggableHandle` to a Child Composable\n\nSince `Modifier.draggableHandle` and `Modifier.longPressDraggableHandle` can only be used in `ReorderableScope`, you may need to pass `ReorderableScope` to a child composable. For example:\n\n```kotlin\n@Composable\nfun List() {\n    // ...\n\n    ReorderableColumn(\n        list = list,\n        onSettle = { fromIndex, toIndex -\u003e\n            // Update the list\n        },\n    ) { index, item, isDragging -\u003e\n        key(item.id) {\n            ReorderableItem {\n                // Item content\n\n                DragHandle(this)\n            }\n        }\n    }\n}\n\n@Composable\nfun DragHandle(scope: ReorderableScope) {\n    IconButton(modifier = with(scope) { Modifier.draggableHandle() }, /* ... */)\n}\n```\n\n##### Use with [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e)\n\nIf you want to use the [material3's Clickable Card](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e), you can create a [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) and pass it to both the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) and the `Modifier.draggableHandle` (or `Modifier.longPressDraggableHandle`), `Modifier.draggableHandle` will emit drag events to the [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) so that the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) can respond to the drag events:\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(4) { \"Item $it\" }) }\n\nReorderableColumn(\n    modifier = Modifier\n        .fillMaxSize()\n        .padding(8.dp),\n    list = list,\n    onSettle = { fromIndex, toIndex -\u003e\n        list = list.toMutableList().apply {\n            add(toIndex, removeAt(fromIndex))\n        }\n    },\n    onMove = {\n        ViewCompat.performHapticFeedback(\n            view,\n            HapticFeedbackConstantsCompat.SEGMENT_FREQUENT_TICK\n        )\n    },\n    verticalArrangement = Arrangement.spacedBy(8.dp),\n) { _, item, _ -\u003e\n    key(item) {\n        ReorderableItem {\n            val interactionSource = remember { MutableInteractionSource() }\n\n            Card(\n                onClick = {},\n                interactionSource = interactionSource,\n            ) {\n                Row {\n                    Text(item, Modifier.padding(horizontal = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                ViewCompat.performHapticFeedback(\n                                    view,\n                                    HapticFeedbackConstantsCompat.GESTURE_START\n                                )\n                            },\n                            onDragStopped = {\n                                ViewCompat.performHapticFeedback(\n                                    view,\n                                    HapticFeedbackConstantsCompat.GESTURE_END\n                                )\n                            },\n                            interactionSource = interactionSource,\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n#### `Row`\n\nSee [`ReorderableRowScreen.kt`](demoApp/composeApp/src/commonMain/kotlin/sh/calvin/reorderable/demo/ui/ReorderableRowScreen.kt) in the demo app.\n\n##### Simple Example\n\nTo use this library with [`Row`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Row(androidx.compose.ui.Modifier,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.ui.Alignment.Vertical,kotlin.Function1)\u003e), follow this basic structure:\n\n```kotlin\nReorderableRow(\n    list = list,\n    onSettle = { fromIndex, toIndex -\u003e\n        // Update the list\n    },\n) { index, item, isDragging -\u003e\n    key(item.id) {\n        ReorderableItem {\n            // Item content\n\n            IconButton(modifier = Modifier.draggableHandle(), /* ... */)\n        }\n    }\n}\n```\n\n##### Complete Example (with haptic feedback)\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(4) { \"Item $it\" }) }\n\nReorderableRow(\n    modifier = Modifier\n        .fillMaxSize()\n        .padding(8.dp),\n    list = list,\n    onSettle = { fromIndex, toIndex -\u003e\n        list = list.toMutableList().apply {\n            add(toIndex, removeAt(fromIndex))\n        }\n    },\n    onMove = {\n        ViewCompat.performHapticFeedback(\n            view,\n            HapticFeedbackConstantsCompat.SEGMENT_FREQUENT_TICK\n        )\n    },\n    verticalArrangement = Arrangement.spacedBy(8.dp),\n) { _, item, isDragging -\u003e\n    key(item) {\n        ReorderableItem {\n            val elevation by animateDpAsState(if (isDragging) 4.dp else 0.dp)\n\n            Surface(shadowElevation = elevation) {\n                Column {\n                    Text(item, Modifier.padding(vertical = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                ViewCompat.performHapticFeedback(\n                                    view,\n                                    HapticFeedbackConstantsCompat.GESTURE_START\n                                )\n                            },\n                            onDragStopped = {\n                                ViewCompat.performHapticFeedback(\n                                    view,\n                                    HapticFeedbackConstantsCompat.GESTURE_END\n                                )\n                            },\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n##### Passing `Modifier.draggableHandle` to a Child Composable\n\nSince `Modifier.draggableHandle` and `Modifier.longPressDraggableHandle` can only be used in `ReorderableScope`, you may need to pass `ReorderableScope` to a child composable. For example:\n\n```kotlin\n@Composable\nfun List() {\n    // ...\n\n    ReorderableRow(\n        list = list,\n        onSettle = { fromIndex, toIndex -\u003e\n            // Update the list\n        },\n    ) { index, item, isDragging -\u003e\n        key(item.id) {\n            ReorderableItem {\n                // Item content\n\n                DragHandle(this)\n            }\n        }\n    }\n}\n\n@Composable\nfun DragHandle(scope: ReorderableScope) {\n    IconButton(modifier = with(scope) { Modifier.draggableHandle() }, /* ... */)\n}\n```\n\n##### Use with [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e)\n\nIf you want to use the [material3's Clickable Card](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e), you can create a [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) and pass it to both the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) and the `Modifier.draggableHandle` (or `Modifier.longPressDraggableHandle`), `Modifier.draggableHandle` will emit drag events to the [`MutableInteractionSource`](https://developer.android.com/reference/kotlin/androidx/compose/foundation/interaction/MutableInteractionSource) so that the [`Card`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/material3/package-summary#Card(kotlin.Function0,androidx.compose.ui.Modifier,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.material3.CardColors,androidx.compose.material3.CardElevation,androidx.compose.foundation.BorderStroke,androidx.compose.foundation.interaction.MutableInteractionSource,kotlin.Function1)\u003e) can respond to the drag events:\n\n```kotlin\nval hapticFeedback = LocalHapticFeedback.current\n\nvar list by remember { mutableStateOf(List(4) { \"Item $it\" }) }\n\nReorderableRow(\n    modifier = Modifier\n        .fillMaxSize()\n        .padding(8.dp),\n    list = list,\n    onSettle = { fromIndex, toIndex -\u003e\n        list = list.toMutableList().apply {\n            add(toIndex, removeAt(fromIndex))\n        }\n    },\n    onMove = {\n        ViewCompat.performHapticFeedback(\n            view,\n            HapticFeedbackConstantsCompat.SEGMENT_FREQUENT_TICK\n        )\n    },\n    verticalArrangement = Arrangement.spacedBy(8.dp),\n) { _, item, _ -\u003e\n    key(item) {\n        ReorderableItem {\n            val interactionSource = remember { MutableInteractionSource() }\n\n            Card(\n                onClick = {},\n                interactionSource = interactionSource,\n            ) {\n                Column {\n                    Text(item, Modifier.padding(vertical = 8.dp))\n                    IconButton(\n                        modifier = Modifier.draggableHandle(\n                            onDragStarted = {\n                                ViewCompat.performHapticFeedback(\n                                    view,\n                                    HapticFeedbackConstantsCompat.GESTURE_START\n                                )\n                            },\n                            onDragStopped = {\n                                ViewCompat.performHapticFeedback(\n                                    view,\n                                    HapticFeedbackConstantsCompat.GESTURE_END\n                                )\n                            },\n                            interactionSource = interactionSource,\n                        ),\n                        onClick = {},\n                    ) {\n                        Icon(Icons.Rounded.DragHandle, contentDescription = \"Reorder\")\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n#### Accessibility\n\nSee the demo app for examples of how to make the reorderable list accessible.\n\nIf the items in the list do not contain any button besides the drag handle, I recommend adding \"Move Up\"/\"Move Down\"/\"Move Left\"/\"Move Right\" actions to the TalkBack menu in each item via [`SemanticsPropertyReceiver.customActions`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/ui/semantics/package-summary#(androidx.compose.ui.semantics.SemanticsPropertyReceiver).customActions()\u003e) and applying [`Modifier.clearAndSetSemantics`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/ui/semantics/package-summary#(androidx.compose.ui.Modifier).clearAndSetSemantics(kotlin.Function1)\u003e) to the drag handle button to make the drag handle button not focusable for TalkBack. For more information, see [Key steps to improve Compose accessibility](https://developer.android.com/develop/ui/compose/accessibility/key-steps#custom-actions).\n\n#### FAQ\n\n##### When `onMove` is called to move items, the dragging item flickers/jumps/flashes.\n\n\u003e [!NOTE]  \n\u003e This assumes you're using version 2.0.3 or later of this library.\n\nThe `onMove` function expects the list to be updated before it returns. If the list is updated after `onMove` returns, the dragging item will flicker. To fix this, update the list before returning from `onMove`.\n\n```kotlin\nval reorderableLazyXXXXState = rememberReorderableLazyXXXXState(listState) { from, to -\u003e\n    // do NOT wrap the updateList call in `launch`\n    updateList(from, to)\n}\n\nsuspend fun updateList(from: Int, to: Int) {\n    // long update operation\n}\n```\n\nIf you can't keep the list update inside `onMove`, you can use a channel to communicate between `onMove` and the list update composition. Here's an example:\n\n```kotlin\nval listUpdatedChannel = remember { Channel\u003cUnit\u003e() }\nval reorderableLazyXXXXState = rememberReorderableLazyXXXXState(listState) { from, to -\u003e\n    // clear the channel\n    listUpdatedChannel.tryReceive()\n\n    // update the list\n\n    // wait for the list to be updated\n    listUpdatedChannel.receive()\n}\n\nLaunchedEffect(list) {\n    // notify the list is updated\n    listUpdatedChannel.trySend(Unit)\n}\n```\n\n## API\n\n### [`LazyColumn`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyColumn(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e) / [`LazyRow`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#LazyRow(androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.LazyListState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.ui.Alignment.Vertical,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e)\n\n- [`rememberReorderableLazyListState`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyList.kt)\n- [`ReorderableItem`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyList.kt)\n- [`Modifier.draggableHandle`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyCollection.kt)\n- [`Modifier.longPressDraggableHandle`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyCollection.kt)\n\n### [`LazyVerticalGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/grid/package-summary#LazyVerticalGrid(androidx.compose.foundation.lazy.grid.GridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.grid.LazyGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e) / [`LazyHorizontalGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/grid/package-summary#LazyHorizontalGrid(androidx.compose.foundation.lazy.grid.GridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.grid.LazyGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e)\n\n- [`rememberReorderableLazyGridState`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyGrid.kt)\n- [`ReorderableItem`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyGrid.kt)\n- [`Modifier.draggableHandle`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyCollection.kt)\n- [`Modifier.longPressDraggableHandle`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyCollection.kt)\n\n### [`LazyVerticalStaggeredGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/staggeredgrid/package-summary#LazyVerticalStaggeredGrid(androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.ui.unit.Dp,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e) / [`LazyHorizontalStaggeredGrid`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/staggeredgrid/package-summary#LazyHorizontalStaggeredGrid(androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells,androidx.compose.ui.Modifier,androidx.compose.foundation.lazy.staggeredgrid.LazyStaggeredGridState,androidx.compose.foundation.layout.PaddingValues,kotlin.Boolean,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.unit.Dp,androidx.compose.foundation.gestures.FlingBehavior,kotlin.Boolean,kotlin.Function1)\u003e)\n\n- [`rememberReorderableLazyStaggeredGridState`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyStaggeredGrid.kt)\n- [`ReorderableItem`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyStaggeredGrid.kt)\n- [`Modifier.draggableHandle`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyCollection.kt)\n- [`Modifier.longPressDraggableHandle`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/ReorderableLazyCollection.kt)\n\n### [`Column`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Column(androidx.compose.ui.Modifier,androidx.compose.foundation.layout.Arrangement.Vertical,androidx.compose.ui.Alignment.Horizontal,kotlin.Function1)\u003e) / [`Row`](\u003chttps://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/package-summary#Row(androidx.compose.ui.Modifier,androidx.compose.foundation.layout.Arrangement.Horizontal,androidx.compose.ui.Alignment.Vertical,kotlin.Function1)\u003e)\n\n- [`ReorderableColumn`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/demo/ReorderableList.kt)\n- [`ReorderableRow`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/demo/ReorderableList.kt)\n- [`Modifier.draggableHandle`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/demo/ReorderableList.kt)\n- [`Modifier.longPressDraggableHandle`](reorderable/src/commonMain/kotlin/sh/calvin/reorderable/demo/ReorderableList.kt)\n\n## Running the demo app\n\nTo run the Android demo app, open the project in Android Studio and run the app.\n\nTo run the iOS demo app, open the iosApp project in Xcode and run the app or add the following Configuration to the Android Studio project, you may need to install the [Kotlin Multiplatform Mobile plugin](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile) first.\n\n![Screenshot 2024-02-10 at 20 58 54](https://github.com/Calvin-LL/Reorderable/assets/8357970/817a17bf-360f-4a0b-9a18-219f9f9eba28)\n\nTo run the web demo app, run `./gradlew :composeApp:wasmJsBrowserDevelopmentRun`.\n\nTo run the desktop demo app, run `./gradlew :demoApp:ComposeApp:run`.\n\n## Contributing\n\nOpen this project with Android Studio Preview.\n\nYou'll want to install the [Kotlin Multiplatform Mobile plugin](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile) in Android Studio before you open this project.\n\n## License\n\n```\nCopyright 2023 Calvin Liang\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","funding_links":[],"categories":["Libraries","Kotlin"],"sub_categories":["Testings"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCalvin-LL%2FReorderable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FCalvin-LL%2FReorderable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCalvin-LL%2FReorderable/lists"}