diff --git a/Sources/ComponentsKit/Components/Alert/SUAlert.swift b/Sources/ComponentsKit/Components/Alert/SUAlert.swift index 741a8ba..eb2b26a 100644 --- a/Sources/ComponentsKit/Components/Alert/SUAlert.swift +++ b/Sources/ComponentsKit/Components/Alert/SUAlert.swift @@ -60,6 +60,7 @@ struct AlertContent: View { .foregroundStyle(UniversalColor.foreground.color) .multilineTextAlignment(.center) .frame(maxWidth: .infinity) + .fixedSize(horizontal: false, vertical: true) } func message(_ text: String) -> some View { diff --git a/Sources/ComponentsKit/Components/Button/SUButton.swift b/Sources/ComponentsKit/Components/Button/SUButton.swift index 2c253d0..550eb57 100644 --- a/Sources/ComponentsKit/Components/Button/SUButton.swift +++ b/Sources/ComponentsKit/Components/Button/SUButton.swift @@ -9,8 +9,8 @@ public struct SUButton: View { /// A closure that is triggered when the button is tapped. public var action: () -> Void - /// A Boolean value indicating whether the button is pressed. - @State public var isPressed: Bool = false + /// A current scale effect value. + @State public var scale: CGFloat = 1.0 // MARK: Initialization @@ -37,17 +37,15 @@ public struct SUButton: View { .buttonStyle(CustomButtonStyle(model: self.model)) .simultaneousGesture(DragGesture(minimumDistance: 0.0) .onChanged { _ in - self.isPressed = true + self.scale = self.model.animationScale.value } .onEnded { _ in - self.isPressed = false + self.scale = 1.0 } ) .disabled(!self.model.isInteractive) - .scaleEffect( - self.isPressed ? self.model.animationScale.value : 1, - anchor: .center - ) + .scaleEffect(self.scale, anchor: .center) + .animation(.easeOut(duration: 0.05), value: self.scale) } @ViewBuilder diff --git a/Sources/ComponentsKit/Components/Button/UKButton.swift b/Sources/ComponentsKit/Components/Button/UKButton.swift index 9653de5..747897b 100644 --- a/Sources/ComponentsKit/Components/Button/UKButton.swift +++ b/Sources/ComponentsKit/Components/Button/UKButton.swift @@ -18,12 +18,14 @@ open class UKButton: FullWidthComponent, UKComponent { /// A Boolean value indicating whether the button is pressed. public private(set) var isPressed: Bool = false { didSet { - self.transform = self.isPressed && self.model.isInteractive - ? .init( - scaleX: self.model.animationScale.value, - y: self.model.animationScale.value - ) - : .identity + UIView.animate(withDuration: 0.05, delay: 0, options: [.curveEaseOut]) { + self.transform = self.isPressed && self.model.isInteractive + ? .init( + scaleX: self.model.animationScale.value, + y: self.model.animationScale.value + ) + : .identity + } } } @@ -197,7 +199,13 @@ open class UKButton: FullWidthComponent, UKComponent { ) { super.touchesCancelled(touches, with: event) - self.isPressed = false + defer { self.isPressed = false } + + if self.model.isInteractive, + let location = touches.first?.location(in: self), + self.bounds.contains(location) { + self.action() + } } open override func traitCollectionDidChange( diff --git a/Sources/ComponentsKit/Components/Card/SUCard.swift b/Sources/ComponentsKit/Components/Card/SUCard.swift index 13cb8c5..63736e7 100644 --- a/Sources/ComponentsKit/Components/Card/SUCard.swift +++ b/Sources/ComponentsKit/Components/Card/SUCard.swift @@ -19,8 +19,8 @@ public struct SUCard: View { /// A closure that is triggered when the card is tapped. public var onTap: () -> Void - /// A Boolean value indicating whether the card is pressed. - @State public var isPressed: Bool = false + /// A current scale effect value. + @State public var scale: CGFloat = 1.0 @ViewBuilder private let content: () -> Content @State private var contentSize: CGSize = .zero @@ -66,16 +66,14 @@ public struct SUCard: View { .simultaneousGesture( DragGesture(minimumDistance: 0.0) .onChanged { _ in - self.isPressed = true + self.scale = self.model.animationScale.value } .onEnded { _ in - self.isPressed = false + self.scale = 1.0 }, isEnabled: self.model.isTappable ) - .scaleEffect( - self.isPressed ? self.model.animationScale.value : 1, - anchor: .center - ) + .scaleEffect(self.scale, anchor: .center) + .animation(.easeOut(duration: 0.05), value: self.scale) } } diff --git a/Sources/ComponentsKit/Components/Card/UKCard.swift b/Sources/ComponentsKit/Components/Card/UKCard.swift index aa63418..8c620dd 100644 --- a/Sources/ComponentsKit/Components/Card/UKCard.swift +++ b/Sources/ComponentsKit/Components/Card/UKCard.swift @@ -29,12 +29,14 @@ open class UKCard: UIView, UKComponent { /// A Boolean value indicating whether the button is pressed. public private(set) var isPressed: Bool = false { didSet { - self.transform = self.isPressed - ? .init( - scaleX: self.model.animationScale.value, - y: self.model.animationScale.value - ) - : .identity + UIView.animate(withDuration: 0.05, delay: 0, options: [.curveEaseOut]) { + self.transform = self.isPressed + ? .init( + scaleX: self.model.animationScale.value, + y: self.model.animationScale.value + ) + : .identity + } } } @@ -168,7 +170,15 @@ open class UKCard: UIView, UKComponent { ) { super.touchesCancelled(touches, with: event) - self.isPressed = false + guard self.model.isTappable else { return } + + defer { self.isPressed = false } + + if self.model.isTappable, + let location = touches.first?.location(in: self), + self.bounds.contains(location) { + self.onTap() + } } open override func traitCollectionDidChange(