Skip to content

Commit 9715b1d

Browse files
add suAlert modifier
1 parent 05e7eed commit 9715b1d

File tree

4 files changed

+123
-1
lines changed

4 files changed

+123
-1
lines changed

Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/AlertPreview.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import SwiftUI
33
import UIKit
44

55
struct AlertPreview: View {
6+
@State var isAlertPresented: Bool = false
67
@State private var model = AlertVM {
78
$0.title = Self.alertTitle
89
$0.message = AlertMessage.short.rawValue
@@ -21,6 +22,15 @@ struct AlertPreview: View {
2122
}
2223
.preview
2324
}
25+
PreviewWrapper(title: "SwiftUI") {
26+
SUButton(model: .init { $0.title = "Show Alert" }) {
27+
self.isAlertPresented = true
28+
}
29+
.suAlert(
30+
isPresented: self.$isAlertPresented,
31+
model: self.model
32+
)
33+
}
2434
Form {
2535
Section("Title") {
2636
Toggle("Has Title", isOn: .init(

Sources/ComponentsKit/Components/Alert/Models/AlertVM.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ extension AlertVM {
8585
$0.color = model.color
8686
$0.cornerRadius = model.cornerRadius
8787
$0.style = model.style
88+
$0.isFullWidth = true
8889
}
8990
}
9091
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import SwiftUI
2+
3+
extension View {
4+
/// A SwiftUI view modifier that presents an alert with a title, message, and up to two action buttons.
5+
///
6+
/// All actions in an alert dismiss the alert after the action runs. If no actions are present, a standard “OK” action is included.
7+
///
8+
/// - Parameters:
9+
/// - isPresented: A binding that determines whether the alert is presented.
10+
/// - model: A model that defines the appearance properties for an alert.
11+
/// - primaryAction: An optional closure executed when the primary button is tapped.
12+
/// - secondaryAction: An optional closure executed when the secondary button is tapped.
13+
/// - onDismiss: An optional closure executed when the alert is dismissed.
14+
///
15+
/// - Example:
16+
/// ```swift
17+
/// SomeView()
18+
/// .suAlert(
19+
/// isPresented: $isAlertPresented,
20+
/// model: .init { alertVM in
21+
/// alertVM.title = "My Alert"
22+
/// alertVM.message = "This is an alert."
23+
/// alertVM.primaryButton = .init { buttonVM in
24+
/// buttonVM.title = "OK"
25+
/// buttonVM.color = .primary
26+
/// buttonVM.style = .filled
27+
/// }
28+
/// alertVM.secondaryButton = .init { buttonVM in
29+
/// buttonVM.title = "Cancel"
30+
/// buttonVM.style = .light
31+
/// }
32+
/// },
33+
/// primaryAction: {
34+
/// NSLog("Primary button tapped")
35+
/// },
36+
/// secondaryAction: {
37+
/// NSLog("Secondary button tapped")
38+
/// },
39+
/// onDismiss: {
40+
/// print("Alert dismissed")
41+
/// }
42+
/// )
43+
/// ```
44+
public func suAlert(
45+
isPresented: Binding<Bool>,
46+
model: AlertVM,
47+
primaryAction: (() -> Void)? = nil,
48+
secondaryAction: (() -> Void)? = nil,
49+
onDismiss: (() -> Void)? = nil
50+
) -> some View {
51+
return self.modal(
52+
isVisible: isPresented,
53+
transitionDuration: model.transition.value,
54+
onDismiss: onDismiss,
55+
content: {
56+
SUCenterModal(
57+
isVisible: isPresented,
58+
model: model.modalVM,
59+
header: {
60+
if model.message.isNotNil,
61+
let title = model.title {
62+
AlertTitle(text: title)
63+
}
64+
},
65+
body: {
66+
if let message = model.message {
67+
AlertMessage(text: message)
68+
} else if let title = model.title {
69+
AlertTitle(text: title)
70+
}
71+
},
72+
footer: {
73+
SUButton(
74+
model: AlertVM.defaultButtonVM,
75+
action: {
76+
primaryAction?()
77+
isPresented.wrappedValue = false
78+
}
79+
)
80+
}
81+
)
82+
}
83+
)
84+
}
85+
}
86+
87+
// MARK: - Helpers
88+
89+
private struct AlertTitle: View {
90+
let text: String
91+
92+
var body: some View {
93+
Text(self.text)
94+
.font(UniversalFont.mdHeadline.font)
95+
.foregroundStyle(UniversalColor.foreground.color)
96+
.multilineTextAlignment(.center)
97+
.frame(maxWidth: .infinity)
98+
}
99+
}
100+
101+
private struct AlertMessage: View {
102+
let text: String
103+
104+
var body: some View {
105+
Text(self.text)
106+
.font(UniversalFont.mdBody.font)
107+
.foregroundStyle(UniversalColor.secondaryForeground.color)
108+
.multilineTextAlignment(.center)
109+
.frame(maxWidth: .infinity)
110+
}
111+
}

Sources/ComponentsKit/Components/Modal/SwiftUI/SUCenterModal.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ struct SUCenterModal<Header: View, Body: View, Footer: View>: View {
5454
extension View {
5555
/// A SwiftUI view modifier that presents a center-aligned modal.
5656
///
57-
/// This modifier allows you to attach a cetner modal to any SwiftUI view, providing a structured way to display modals
57+
/// This modifier allows you to attach a center modal to any SwiftUI view, providing a structured way to display modals
5858
/// with a header, body, and footer, all styled and laid out according to the provided `CenterModalVM` model.
5959
///
6060
/// - Parameters:

0 commit comments

Comments
 (0)