{"id":13496811,"url":"https://github.com/c-villain/SwipeActions","last_synced_at":"2025-03-28T19:31:11.345Z","repository":{"id":39273504,"uuid":"441467722","full_name":"c-villain/SwipeActions","owner":"c-villain","description":"Swipe actions, swipe menu based on SwiftUI","archived":false,"fork":false,"pushed_at":"2023-05-17T12:20:13.000Z","size":2883,"stargazers_count":163,"open_issues_count":4,"forks_count":19,"subscribers_count":5,"default_branch":"main","last_synced_at":"2024-04-14T11:57:29.811Z","etag":null,"topics":["ios13","swiftui","swiftui-animations","swiftui-framework","swipeactions","swipemenu"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/c-villain.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}},"created_at":"2021-12-24T13:04:10.000Z","updated_at":"2024-03-29T00:29:22.000Z","dependencies_parsed_at":"2024-03-13T21:47:09.287Z","dependency_job_id":null,"html_url":"https://github.com/c-villain/SwipeActions","commit_stats":{"total_commits":75,"total_committers":4,"mean_commits":18.75,"dds":0.4666666666666667,"last_synced_commit":"feadf8ab260ae55ceec07fa589f176586fb2b2d5"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c-villain%2FSwipeActions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c-villain%2FSwipeActions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c-villain%2FSwipeActions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/c-villain%2FSwipeActions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/c-villain","download_url":"https://codeload.github.com/c-villain/SwipeActions/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246088445,"owners_count":20721688,"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","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":["ios13","swiftui","swiftui-animations","swiftui-framework","swipeactions","swipemenu"],"created_at":"2024-07-31T19:02:00.504Z","updated_at":"2025-03-28T19:31:10.646Z","avatar_url":"https://github.com/c-villain.png","language":"Swift","funding_links":[],"categories":["Swift"],"sub_categories":[],"readme":"# SwipeActions\n\n[![Latest release](https://img.shields.io/github/v/release/c-villain/SwipeActions?color=brightgreen\u0026label=version)](https://github.com/c-villain/SwipeActions/releases/latest)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fc-villain%2FSwipeActions%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/c-villain/SwipeActions)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fc-villain%2FSwipeActions%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/c-villain/SwipeActions)\n[![](https://img.shields.io/badge/SPM-supported-DE5C43.svg?color=brightgreen)](https://swift.org/package-manager/)\n![](https://img.shields.io/github/license/c-villain/SwipeActions)\n\n[![contact: @lexkraev](https://img.shields.io/badge/contact-%40lexkraev-blue.svg?style=flat)](https://t.me/lexkraev)\n[![Telegram Group](https://img.shields.io/endpoint?color=neon\u0026style=flat-square\u0026url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fswiftui_dev)](https://telegram.dog/swiftui_dev)\n\n\u003cp align=\"left\"\u003e\n\u003cimg src=\"Sources/Gifs/teaser.jpg\" alt=\"corner radius\" width=\"600\"\u003e\n\u003c/p\u003e\n\nLibrary for creating fully customizable swipe actions for any SwiftUI View, similar to Apple's [```swipeActions(edge:allowsFullSwipe:content:)```](https://developer.apple.com/documentation/swiftui/view/swipeactions(edge:allowsfullswipe:content:)) that available from iOS 15 and only in [List](https://developer.apple.com/documentation/swiftui/lists) 🤷🏼‍♂️.\nYou can use ```SwipeActions``` in project targeting iOS 13 with any view (e.g. ```Text``` or ```VStack```).\n\n👨🏻‍💻 Feel free to subscribe to channel **[SwiftUI dev](https://t.me/swiftui_dev)** in telegram.\n\n## Requirements\n\n- iOS 13.0 or macOS 10.15\n\n## Comparison table\n\n| Features support | This SPM | Others |\n| :---         |     :---:      |          :---:  |\n| SwiftUI   | 🟢     | 🟢     |\n| SPM    | 🟢        | 🟢       |\n| MacOS    | 🟢        | 🔴       |\n| iOS 13.0    | 🟢        | 🔴       |\n| RTL Languages    | 🟢        | 🔴       |\n| FullSwipe Mode   | 🟢        | 🔴       |\n| Flexibility   | 🟢        | 🟡       |\n| Haptics   | 🟢        | 🟡       |\n| Ease of Use    | 🟢        | 🔴       |\u2028\n\n\n## Installation\n\n#### Swift Package Manager\n\nTo integrate ```SwipeActions``` into your project using SwiftPM add the following to your `Package.swift`:\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/c-villain/SwipeActions\", from: \"0.1.0\"),\n],\n```\nor via [XcodeGen](https://github.com/yonaskolb/XcodeGen) insert into your `project.yml`:\n\n```yaml\nname: YourProjectName\noptions:\n  deploymentTarget:\n    iOS: 13.0\npackages:\n  SwipeActions:\n    url: https://github.com/c-villain/SwipeActions\n    from: 0.1.0\ntargets:\n  YourTarget:\n    type: application\n    ...\n    dependencies:\n       - package: SwipeActions\n```\n\n## Types\n\nDifferent types of menu: \n- .swiped\n- .slided\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"Sources/Gifs/menuTypes.gif\" alt=\"Example for .swiped and .slided menu\" height=\"100\" width=\"280\"\u003e\n\u003c/p\u003e\n\nBoth types can be upgraded with full swiping:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"Sources/Gifs/fullSwipe.gif\" alt=\"Example of full swipe with non-destructive role\" width=\"280\"\u003e\n\u003c/p\u003e \n\n## Quick start\n\n\u003cdetails\u003e\n  \u003csummary\u003eAdding both leading and trailing swipe actions:\u003c/summary\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"Sources/Gifs/both.gif\" alt=\"Example with leading and trailing swipes\" height=\"160\" width=\"280\"\u003e\n\u003c/p\u003e\n\nUse ```Leading { ... }``` and ```Trailing { ... }``` closures inside ```.addSwipeAction { ... }``` modifier:\n\n```swift\nimport SwipeActions\n\nstruct YourView: View {\n    \n    var body: some View {\n        ScrollView {\n            LazyVStack {\n                ForEach(1...100, id: \\.self) { cell in\n                    Text(\"Cell \\(cell)\")\n                        .frame(height: 50, alignment: .center)\n                        .frame(maxWidth: .infinity)\n                        .contentShape(Rectangle())\n                        .addSwipeAction {\n                            Leading { //\u003c= HERE \n                                Button {\n                                    print(\"edit \\(cell)\")\n                                } label: {\n                                    Image(systemName: \"pencil\")\n                                        .foregroundColor(.white)\n                                }\n                                .frame(width: 60, height: 50, alignment: .center)\n                                .contentShape(Rectangle())\n                                .background(Color.green)\n\n                            }\n                            Trailing { //\u003c= HERE \n                                HStack(spacing: 0) {\n                                    Button {\n                                        print(\"remove \\(cell)\")\n                                    } label: {\n                                        Image(systemName: \"trash\")\n                                            .foregroundColor(.white)\n                                    }\n                                    .frame(width: 60, height: 50, alignment: .center)\n                                    .contentShape(Rectangle())\n                                    .background(Color.red)\n    \n                                    Button {\n                                        print(\"Inform \\(cell)\")\n                                    } label: {\n                                        Image(systemName: \"bell.slash.fill\")\n                                            .foregroundColor(.white)\n                                    }\n                                    .frame(width: 60, height: 50, alignment: .center)\n                                    .background(Color.blue)\n                                }\n                            }\n                        }\n                }\n            }\n        }\n    }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eAdding several actions on the side:\u003c/summary\u003e\n\nDon't forget that your actions are subviews in general and buttons or smth else particularly. Please arrange them:\n\n```swift\nYourView()\n.addSwipeAction(edge: .trailing) {\n    HStack(spacing: 0) { // \u003c= 👀 Look here \n        Rectangle()\n            .fill(Color.green.opacity(0.8))\n            .frame(width: 8.0, height: 80)\n        \n        Button {\n        } label: {\n            Image(systemName: \"message\")\n                .foregroundColor(.white)\n                .frame(width: 60, height: 80)\n                .contentShape(Rectangle())\n        }\n        .background(Color.blue)\n    }\n}\n\n```\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n  \u003csummary\u003eAdding swipe actions to the one side of the view:\u003c/summary\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"Sources/Gifs/trailing.gif\" alt=\"Example with trailing swipe menu\" height=\"160\" width=\"280\"\u003e\n\u003c/p\u003e\n\nUse ```.addSwipeAction(edge: ) { ... }``` modifier, ```edge``` - a ```HorizontalAlignment``` value input parameter - with two cases of using ```.leading``` or ```.trailing```\n\n```swift\nimport SwipeActions\n\nstruct YourView: View {\n    \n    var body: some View {\n        ScrollView {\n            LazyVStack {\n                ForEach(1...100, id: \\.self) { cell in\n                    Text(\"Cell \\(cell)\")\n                        .frame(height: 50, alignment: .center)\n                        .frame(maxWidth: .infinity)\n                        .contentShape(Rectangle())\n                        .addSwipeAction(edge: .trailing) { // \u003c= choose here .trailing or .leading\n                            HStack(spacing: 0) {\n                                Button {\n                                    print(\"remove \\(cell)\")\n                                } label: {\n                                    Image(systemName: \"trash\")\n                                        .foregroundColor(.white)\n                                }\n                                .frame(width: 60, height: 50, alignment: .center)\n                                .contentShape(Rectangle())\n                                .background(Color.red)\n                                \n                                Button {\n                                    print(\"Inform \\(cell)\")\n                                } label: {\n                                    Image(systemName: \"bell.slash.fill\")\n                                        .foregroundColor(.white)\n                                }\n                                .frame(width: 60, height: 50, alignment: .center)\n                                .background(Color.blue)\n                            }\n                        }\n                }\n            }\n        }\n    }\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eFor automatically closing other opened actions during sliding: \u003c/summary\u003e\n  \n\u003cp align=\"center\"\u003e\n\u003cimg src=\"Sources/Gifs/autoclosing.gif\" alt=\"Example with auto closing swipe actions\" width=\"280\"\u003e\n\u003c/p\u003e \n  \n  Add ```SwipeState``` var to your ```View``` and pass it as a ```binding``` in ```.addSwipeAction(state:)```:\n  \n  ```swift\n  \nstruct YourView: View {  \n     @State var state: SwipeState = .untouched // \u003c= HERE\n\n     var body: some View {\n          ScrollView {\n               VStack(spacing: 2) {\n                   ForEach(1 ... 30, id: \\.self) { cell in\n                       Text(\"Cell \\(cell)\")\n                           .addSwipeAction(state: $state) { // \u003c= HERE\n                              ....\n                           }\n                    }\n               }\n          }\n     }\n}\n```\n  \n \u003c/details\u003e\n \n### Full swipe action\n  \n  For full swipe use modifier ```.addFullSwipeAction(menu:swipeColor:swipeRole:state:content:action:)```\n  \n  Basically there are two main ```SwipeRole``` for full swipe action: ```.destructive``` (defaults) and other one.\n  \n  \u003cdetails\u003e\n  \u003csummary\u003e.destructive\u003c/summary\u003e\n  \n  This role is used for closing/hiding/removing cell.\n  \n  \n\u003cp align=\"center\"\u003e\n\u003cimg src=\"Sources/Gifs/destructiveFullSwipe.gif\" alt=\"Example of full swipe with destructive role\" width=\"280\"\u003e\n\u003c/p\u003e \n     \n  \n  ```swift\n  \nstruct YourView: View {  \n     \n     @State var range: [Int] = [1,2,3,4,5,6,7,8,9,10]\n\n     var body: some View {\n          ScrollView {\n               VStack(spacing: 2) {\n                   ForEach(range, id: \\.self) { cell in\n                       Text(\"Cell \\(cell)\")\n                           .addFullSwipeAction(\n                               menu: .slided,\n                               swipeColor: .red) { // \u003c= Color is the same as last button in Trailing for full effect \n                                    Leading { \n                                        ...\n                                    }\n                                    Trailing {\n                                        ...\n                                        \n                                        Button {\n                                            withAnimation { \n                                                if let index = range.firstIndex(of: cell) {\n                                                    range.remove(at: index)\n                                                }\n                                            }\n                                        } label: {\n                                            Image(systemName: \"trash\")\n                                                .foregroundColor(.white)\n                                        }\n                                        .contentShape(Rectangle())\n                                        .frame(width: 60)\n                                        .frame(maxHeight: .infinity)\n                                        .background(Color.red) // \u003c=== Look here\n                                    }\n                                } action: { // \u003c= action for full swiping\n                                    withAnimation {\n                                        if let index = range.firstIndex(of: cell) {\n                                            range.remove(at: index)\n                                        }\n                                    }\n                                }\n                    }\n               }\n          }\n     }\n}\n```\n   \u003c/details\u003e\n   \n   \n  \u003cdetails\u003e\n  \u003csummary\u003e.default\u003c/summary\u003e\n  \n  This role is used for making some action on cell.\n  \n\u003cp align=\"center\"\u003e\n\u003cimg src=\"Sources/Gifs/nondestructiveFullSwipe.gif\" alt=\"Example of full swipe with non-destructive role\" width=\"280\"\u003e\n\u003c/p\u003e \n     \n  \n  ```swift\n  \nstruct YourView: View {  ]\n\n     var body: some View {\n          ScrollView {\n               VStack(spacing: 2) {\n                   ForEach(1...10, id: \\.self) { cell in\n                       Text(\"Cell \\(cell)\")\n                           .addFullSwipeAction(menu: .slided,\n                                               swipeColor: .green, // \u003c=== Color is the same as last button in Trailing for full effect \n                                               swipeRole: .defaults) {  // \u003c=== Add this parameter\n                                    Leading { \n                                        ...\n                                    }\n                                    Trailing {\n                                        HStack(spacing: 0) {\n                                            ...\n                                            \n                                            Button {\n            \n                                            } label: {\n                                                Image(systemName: \"trash\")\n                                                    .foregroundColor(.white)\n                                            }\n                                            .contentShape(Rectangle())\n                                            .frame(width: 60)\n                                            .frame(maxHeight: .infinity)\n                                            .background(Color.green) // \u003c=== Look here\n                                        }\n                                    }\n                                } action: { // \u003c=== action for full swiping\n                                    ...\n                                }\n                    }\n               }\n          }\n     }\n}\n```\n   \u003c/details\u003e\n \n### Recommendations for use\n\n\u003cdetails\u003e\n  \u003csummary\u003eWith dynamic height content.\u003c/summary\u003e\n \n \nuse ```.frame(maxHeight: .infinity)```\n\n```swift\nYourView()\n    .addSwipeAction(menu: .slided, edge: .trailing) {\n        Button {\n            ...\n        } label: {\n            Image(\"trash\")\n                .font(.system(size: 20.0))\n                .foregroundColor(.white)\n                .frame(width: 68, alignment: .center)\n                .frame(maxHeight: .infinity) // \u003c= Look here\n                .background(.red)\n        }\n    }\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eWith transparent colored views.\u003c/summary\u003e\n \n There is *no* restrictions or any recommendations for using with ```.slided``` type! \n \n With ```.swiped``` use *non-tranparent* color layer or the same color with ```alfa = 1.0```:\n\n```swift\nForEach(1 ... 30, id: \\.self) { cell in\n   Text(\"Cell \\(cell)\")\n       .padding()\n       .frame(height: 80)\n       .frame(maxWidth: .infinity)\n       //.background(Color.green.opacity(0.2)) // \u003c== ❌ DON'T USE SUCH WAY!\n       //.background(Color(red: 0.841, green: 0.956, blue: 0.868)) // \u003c== ✅ USE THIS WAY!\n       .background( // \u003c== OR THIS WAY!\n           ZStack {\n               Color(UIColor.systemBackground) // non-transparent color layer\n               Color.green.opacity(0.2)\n           }\n       )\n       .contentShape(Rectangle())\n       .listStyle(.plain)\n       .addSwipeAction(menu: .swiped, // \u003c=== SWIPED TYPE\n                       state: $state) {\n           Leading {\n           ...\n           }\n       }\n       ...\n }\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eWith List.\u003c/summary\u003e\n\nBasically if you have minimum deployments target for your app is iOS 15 I recommend to use Apple's [swipe actions](https://developer.apple.com/documentation/swiftui/view/swipeactions(edge:allowsfullswipe:content:)) for List. Anyway you may use this.\n\nDue to some features for working with ```List``` you should:\n\n - specify a frame for cell width, e.g. ```.frame(width: UIScreen.main.bounds.size.width - 32, height: 80)``` and a frame for buttons on swipe actions, e.g. ```.frame(width: 60, height: 80)```. Note that height in frames should be the same!\n \n - add modifier ```.onTapGesture { ... }``` for cell to override tapping on swipe action buttons\n \n - add modifier ```.listRowInsets(EdgeInsets())``` for cell\n \n```swift\nList(elements) { e in\n    Text(e.name)\n        .frame(width: UIScreen.main.bounds.size.width - 32, height: 80) // \u003c= HERE\n        .background(Color(UIColor.systemBackground))\n        .onTapGesture { // \u003c=== HERE\n            print(\"on cell tap!\")\n        }\n        .addSwipeAction(menu: .swiped,\n                        edge: .trailing,\n                        state: $state) {\n            Button {\n                print(\"remove\")\n            } label: {\n                Image(systemName: \"trash\")\n                    .foregroundColor(.white)\n            }\n            .frame(width: 60, height: 80, alignment: .center) // \u003c= HERE\n            .contentShape(Rectangle())\n            .background(Color.red)\n        }\n                        .listRowInsets(EdgeInsets()) // \u003c=== HERE\n}\n.padding(16)\n```\n\nLook for code in the example.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eWith no horizontal padding views.\u003c/summary\u003e\n\nTo avoid effect when content in swipe actions started showing immediately after view with no horizontal padding\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"Sources/Gifs/demoWithoutInsets.gif\" alt=\"Demo without insets\" width=\"280\"\u003e\n\u003c/p\u003e\n\nin ```.addSwipeAction { ... }``` add ```Rectangle``` filled with *same* color as root view:\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"Sources/Gifs/demoWithInsets.gif\" alt=\"Demo with insets\" width=\"280\"\u003e\n\u003c/p\u003e\n\n```swift\n YourView()\n     .frame(height: 80)\n     .frame(maxWidth: .infinity)\n     .background(Color.green.opacity(0.8)) // \u003c= Look here\n     .addSwipeAction(edge: .trailing) {\n        HStack(spacing: 0) {\n             Rectangle() // \u003c=== HERE!\n                 .fill(Color.green.opacity(0.8)) // \u003c= 💡 Don't forget!\n                 .frame(width: 8.0, height: 80)\n    \n             Button {\n             } label: {\n                 Image(systemName: \"message\")\n                     .foregroundColor(.white)\n             }\n             .frame(width: 60, height: 80)\n             .contentShape(Rectangle())\n             .background(Color.blue)\n        }\n     }\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eWith context menu.\u003c/summary\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"Sources/Gifs/withContextMenuDemo.gif\" alt=\"Demo without insets\" width=\"280\"\u003e\n\u003c/p\u003e\n\nDue to some difficulties for SwiftUI to detect gestures for sliding view and opening context menu I recommend you to use\n`.contextMenu` after `.addSwipeAction` (or `addFullSwipeAction`):\n\n```swift\n YourView()\n     .frame(height: 80)\n     .frame(maxWidth: .infinity)\n    .contentShape(Rectangle()) \n    .padding()\n    .background(Color(UIColor.systemBackground))\n    .addFullSwipeAction(...) { ... }  // \u003c=== Look here!\n    .contextMenu { ... }\n```\n\nActually if you don't use `.contentShape(Rectangle())`, you can also add `.contextMenu` before `.addSwipeAction` (or `addFullSwipeAction`):\n\n```swift\n YourView()\n     .frame(height: 80)\n     .frame(maxWidth: .infinity)\n    //.contentShape(Rectangle()) // \u003c=== Look here!\n    .padding()\n    .contextMenu { ... } // \u003c=== Look here!\n    .background(Color(UIColor.systemBackground))\n    .addFullSwipeAction(...) { ... } // \u003c=== Look here!\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eHow to add swipe hint.\u003c/summary\u003e\n\nUse modifier `.swipeHint`:\n\nThe place for applying this modifier depends on type of menu.\n\nAdd `.swipeHint` strictly after `.addSwipeAction` for `.slided` type of menu 👇🏻\n```swift\nForEach(range, ...) {\n    YourCell()\n        ...\n        .addFullSwipeAction(\n            menu: .slided, // \u003c== LOOK HERE\n            swipeColor: .red,\n            state: $state) {\n                Leading {\n                    ...\n                }\n                Trailing {\n                    ...\n                }\n            }\n        .swipeHint(cell == range.first, hintOffset: 120.0) // for trailing \u003c== LOOK HERE\n        .swipeHint(cell == range[1] , hintOffset: -120.0) // for leading \u003c== LOOK HERE\n    ...\n}\n```\n\nAdd `.swipeHint` strictly before `.addSwipeAction` for `.swiped` type of menu 👇🏻\n```swift\nForEach(range, ...) {\n    YourCell()\n        ...\n        .swipeHint(cell == range.first, hintOffset: 120.0) // for trailing \u003c== LOOK HERE\n        .swipeHint(cell == range[1], hintOffset: -120.0) // for leading \u003c== LOOK HERE\n        .addFullSwipeAction(\n            menu: .swiped, // \u003c== Look here\n            swipeColor: .red,\n            state: $state) {\n                Leading {\n                    ...\n                }\n                Trailing {\n                    ...\n                }\n            }\n    ...\n}\n```\n\n\u003c/details\u003e\n\n\n\u003cdetails\u003e\n    \u003csummary\u003eMultitouching.\u003c/summary\u003e\n\nDue to SwiftUI philosophy is not quite possible to control multitouching in general and dragging several cells particularly. Anyway we can disable multitouch with special view modifier: `.allowMultitouching(false)` based on UIKit. Add this modifier strictly before using swipe actions:\n\n```swift\n...\nYourView(...)\n      .allowMultitouching(false) // \u003c= Look here\n      .addSwipeAction( ...) {\n        ...\n      }\n...\n```\nBy default this flag is true. Using this modifier will repeat telegram's behaviour where you can drag only one cell during multitouching. \n\nActually the problem exist only in fullswiping mode. In default mode you can drag several cells but after ending touching only one will be opened.\n\nBut as soon as this solution is based on UIKit you can't optimise rendering of `YourView` with `drawingGroup()`:\n```swift\n...\nYourView(...)\n      .allowMultitouching(false) // \u003c= look here\n      .addSwipeAction( ...) {\n        ...\n      }\n      .drawingGroup() // \u003c=  ❌ DON'T DO THAT\n...\n```\n\nYou'll definitely get this:\n\n\u003cimg width=\"338\" alt=\"Drawing group after swipeactions\" src=\"https://github.com/user-attachments/assets/b8671c69-a5e1-4ca7-8d62-67b68bd2d33f\"\u003e\n\nActually rendering will be optimizing by SwiftUI engine... For full control you can add view modifier `.identifier(your id)` to `YourView(...)`\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003eOptimize rendering.\u003c/summary\u003e\n\nTo control view's id for optimizing you should use modifier `.identifier(your id)`:\n\n```swift\nForEach(...) { cell in\n     YourView(cell)\n         .addSwipeAction(...) {}\n         .identifier(cell) // \u003c= Look here\n }\n```\n\nActually if you forget to add identifier this don't worry, id will be added manually.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n    \u003csummary\u003eSwipe sensitivity.\u003c/summary\u003e\n\nTo control swipe sensitivity (minimum distance for dragging) you should use modifier `swipeSensitive`.\n\n```swift\nForEach(...) { cell in\n     YourView(cell)\n         .addSwipeAction(...) {}\n         .swipeSensitive(.medium) // \u003c= Look here. You can control it here \n }\n .swipeSensitive(.medium) // \u003c= Look here. Or here! \n```\n\nIf you forget to add sensitivity, don't worry the system will provide its own default `low` value. Actually it is the most comfortable behavior.\n\n\u003c/details\u003e\n\n\n### Supporting Right to left\n\nThis Library supports right-to-left languages like Arabic and Hebrew. \n\nCheck it by adding `.environment(\\.layoutDirection, .rightToLeft)` to your view with swipe actions.\n\n\u003cdetails\u003e\n\u003csummary\u003eLook for the example\u003c/summary\u003e\n\n```swift\nstruct ContentView: View {\n    var body: some View {\n        LazyVStack {\n            ForEach(0..\u003c5) { index in\n                Text(\"Item \\(index)\")\n                    .swipeActions {\n                        Button(\"Delete\") {\n                            print(\"Item deleted\")\n                        }\n                        .tint(.red)\n                    }\n            }\n        }\n        .environment(\\.layoutDirection, .rightToLeft) // \u003c= Look here\n    }\n}\n```\n\n\u003c/details\u003e\n\n### Haptics Supporting \n\nBy default in the full swiping mode action has haptic feedback.\n\nTo disable it use `.allowFullSwipeHaptics(false)`\n\n\u003cdetails\u003e\n\u003csummary\u003eLook for the example\u003c/summary\u003e\n\n```swift\nYourView()\n    .addFullSwipeAction(...) { ... }\n    .allowFullSwipeHaptics(false) // \u003c= Look here\n```\n\n\u003c/details\u003e\n\nYou can easily change this feedback type with `.fullSwipeHapticFeedback(:)`.\n\n\u003cdetails\u003e\n\u003csummary\u003eLook for the example\u003c/summary\u003e\n\n```swift\nYourView()\n    .addFullSwipeAction(...) { ... }\n    .fullSwipeHapticFeedback(.medium()) // \u003c= Look here\n```\n\n\u003c/details\u003e\n\nYou can easily add haptic to your own buttons in swipe actions.\n\n\u003cdetails\u003e\n\u003csummary\u003eLook for the example\u003c/summary\u003e\n\n```swift\nYourView()\n    .addFullSwipeAction(...) { \n        ... \n    Trailing {\n        Button {\n            HapticsProvider.sendHapticFeedback(.heavy()) // \u003c= Look here\n                ...\n            } label: { ... }\n     }\n}\n```\n\n\u003c/details\u003e\n\n## Communication\n\n- If you **found a bug**, open an issue or submit a fix via a pull request.\n- If you **have a feature request**, open an issue or submit a implementation via a pull request or hit me up on **lexkraev@gmail.com** or **[telegram](https://t.me/lexkraev)**.\n- If you **want to contribute**, submit a pull request onto the master branch.\n\n## License\n\nSwipeActions package is released under an MIT license.\n\n## Special thanks\n\nThx to [Prafulla Singh](https://prafullkumar77.medium.com/) for inspriration with his [SwiftUI tutorial](https://prafullkumar77.medium.com/swiftui-how-to-make-custom-swipe-able-cell-727a27abdddd).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fc-villain%2FSwipeActions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fc-villain%2FSwipeActions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fc-villain%2FSwipeActions/lists"}