// // HoldToCommitButton.swift // Severed // import SwiftUI /// The deliberate-friction commit button: the user must press and hold for a /// second to save a rule, mirroring the reference app's "Hold to Commit". struct HoldToCommitButton: View { var title = "Hold to Commit" var holdDuration: Double = 1.0 let action: () -> Void @State private var progress: Double = 0 var body: some View { ZStack { RoundedRectangle(cornerRadius: 28) .fill(Theme.surfaceElevated) GeometryReader { proxy in RoundedRectangle(cornerRadius: 28) .fill(Theme.commitGradient) .opacity(0.85) .frame(width: proxy.size.width * progress) .animation(.linear(duration: 0.1), value: progress == 0) } Text(title) .font(.system(size: 17, weight: .semibold)) .foregroundStyle(.white) } .frame(height: 56) .clipShape(RoundedRectangle(cornerRadius: 28)) .contentShape(RoundedRectangle(cornerRadius: 28)) .onLongPressGesture(minimumDuration: holdDuration) { progress = 0 action() } onPressingChanged: { pressing in withAnimation(.linear(duration: pressing ? holdDuration : 0.2)) { progress = pressing ? 1 : 0 } } .accessibilityElement(children: .ignore) .accessibilityAddTraits(.isButton) .accessibilityIdentifier("holdToCommitButton") .accessibilityLabel(title) } } #Preview { HoldToCommitButton { } .padding() .background(Theme.background) }