Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e6b5fb9
Implement multi-button swipeActions for Android
Davedeji May 14, 2026
085fcd5
swipeActions: add SKIP @bridge variant + return any View
Davedeji May 14, 2026
f86590e
Fix RenderSwipeableItem unbounded-height crash inside LazyColumn
Davedeji May 14, 2026
fe30985
swipeActions: low-friction snap and velocity-aware fling
Davedeji May 14, 2026
4955923
swipeActions: snap to nearest anchor with velocity projection
Davedeji May 14, 2026
652ef11
swipeActions: drop shared Animatable to fix midway-hang on release
Davedeji May 14, 2026
8067e5c
swipeActions: stricter full-swipe trigger
Davedeji May 14, 2026
0f9bec5
swipeActions: only one row's actions visible at a time
Davedeji May 14, 2026
88335c7
swipeActions: hide opposite-edge reveal during a full swipe
Davedeji May 14, 2026
bb61f84
swipeActions: clip to row bounds and add fade-to-gray scrim
Davedeji May 14, 2026
5844647
swipeActions: constrain reverse-swipe to closing only
Davedeji May 14, 2026
396195c
swipeActions: also constrain release-time projection by start-side
Davedeji May 14, 2026
45d460b
swipeActions: promote destructive to edge + auto-delete on full swipe
Davedeji May 14, 2026
8dfa6e9
swipeActions: tap on destructive button also auto-deletes the row
Davedeji May 14, 2026
c45a41b
swipeActions: dynamic button width, font/padding, edge color match
Davedeji May 14, 2026
02ef098
swipeActions: cleanup code and comments
Davedeji May 14, 2026
d547521
Merge branch 'skiptools:main' into swipe-actions
Davedeji May 14, 2026
6b68d4e
swipeActions: stretch reveal to the row edge + destructive takeover
Davedeji May 14, 2026
e0841ee
swipeAction: Refactor to use AnchorDraggable
Davedeji May 15, 2026
150419b
swipeActions: propagate tint color from button config
Davedeji May 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions Sources/SkipUI/SkipUI/Commands/SwipeActions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2023–2026 Skip
// SPDX-License-Identifier: MPL-2.0
#if !SKIP_BRIDGE
import Foundation

extension View {
public func swipeActions(edge: HorizontalEdge = .trailing, allowsFullSwipe: Bool = true, @ViewBuilder content: () -> any View) -> any View {
#if SKIP
return ModifiedContent(content: self, modifier: SwipeActionsModifier(edge: edge, allowsFullSwipe: allowsFullSwipe, content: ComposeBuilder.from(content)))
#else
return self
#endif
}

// SKIP @bridge
public func swipeActions(bridgedEdge: Int, allowsFullSwipe: Bool, bridgedActions: any View) -> any View {
let edge = HorizontalEdge(rawValue: bridgedEdge) ?? .trailing
return swipeActions(edge: edge, allowsFullSwipe: allowsFullSwipe, content: { bridgedActions })
}
}

#if SKIP
/// Holds a single edge's swipe action configuration.
struct SwipeActionsConfig {
let allowsFullSwipe: Bool
let content: ComposeBuilder
}

final class SwipeActionsModifier: RenderModifier {
let edge: HorizontalEdge
let allowsFullSwipe: Bool
let content: ComposeBuilder

init(edge: HorizontalEdge, allowsFullSwipe: Bool, content: ComposeBuilder) {
self.edge = edge
self.allowsFullSwipe = allowsFullSwipe
self.content = content
super.init()
}

/// Walk the modifier chain and collect leading + trailing swipe configs.
/// Innermost modifier on a given edge wins (matches SwiftUI semantics).
static func combined(for renderable: Renderable) -> (leading: SwipeActionsConfig?, trailing: SwipeActionsConfig?) {
var leading: SwipeActionsConfig? = nil
var trailing: SwipeActionsConfig? = nil
renderable.forEachModifier {
if let mod = $0 as? SwipeActionsModifier {
let config = SwipeActionsConfig(allowsFullSwipe: mod.allowsFullSwipe, content: mod.content)
if mod.edge == .leading {
leading = leading ?? config
} else {
trailing = trailing ?? config
}
}
return nil
}
return (leading: leading, trailing: trailing)
}
}
#endif
#endif
Loading