## Swipe action arming (swipe to archive)

- Use case: Swiping a row until the action arms ("release to archive") — a tick when it arms and when it disarms.
- Feel: A selection tick on crossing the commit point in either direction, so the finger knows the state flipped.
- APIs: UISelectionFeedbackGenerator, DragGesture
- Minimum OS: iOS 10+

### SwiftUI

```swift
import SwiftUI

struct SwipeableRow: View {
    let title: String
    let onArchive: () -> Void

    @State private var offsetX: CGFloat = 0
    @State private var armed = false
    private let commitPoint: CGFloat = -96
    private let tick = UISelectionFeedbackGenerator()

    var body: some View {
        ZStack(alignment: .trailing) {
            Color.orange
            Label("Archive", systemImage: "archivebox")
                .foregroundStyle(.white).padding(.trailing, 24)

            Text(title)
                .frame(maxWidth: .infinity, alignment: .leading)
                .padding().background(.background)
                .offset(x: offsetX)
                .gesture(
                    DragGesture()
                        .onChanged { value in
                            offsetX = min(0, value.translation.width)
                            let nowArmed = offsetX < commitPoint
                            if nowArmed != armed {
                                armed = nowArmed
                                tick.selectionChanged() // arm & disarm
                            }
                        }
                        .onEnded { _ in
                            if armed { onArchive() }
                            withAnimation(.spring) { offsetX = 0; armed = false }
                        }
                )
        }
        .clipShape(RoundedRectangle(cornerRadius: 12))
        .frame(height: 56)
    }
}
```

### Notes
- Ticking on disarm as well as arm is what lets users back out confidently without looking.
- System swipeActions {} in List already provide this — hand-roll only for custom rows.
