Skip to content

Commit 82e3e23

Browse files
add docs for center and bottom modal modifiers
1 parent ce07794 commit 82e3e23

File tree

2 files changed

+298
-0
lines changed

2 files changed

+298
-0
lines changed

Sources/ComponentsKit/Modal/SwiftUI/SUBottomModal.swift

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,45 @@ struct SUBottomModal<Header: View, Body: View, Footer: View>: View {
9090
// MARK: - Presentation Helpers
9191

9292
extension View {
93+
/// A SwiftUI view modifier that presents a bottom-aligned modal.
94+
///
95+
/// This modifier allows you to attach a bottom modal to any SwiftUI view, providing a structured way to display modals
96+
/// with a header, body, and footer, all styled and laid out according to the provided `BottomModalVM` model.
97+
///
98+
/// - Parameters:
99+
/// - isPresented: A binding that determines whether the modal is presented.
100+
/// - model: A model that defines the appearance properties.
101+
/// - onDismiss: An optional closure executed when the modal is dismissed.
102+
/// - header: A closure that provides the view for the modal's header.
103+
/// - body: A closure that provides the view for the modal's main content.
104+
/// - footer: A closure that provides the view for the modal's footer.
105+
///
106+
/// - Returns: A modified `View` with a bottom modal attached.
107+
///
108+
/// - Example:
109+
/// ```swift
110+
/// SomeView()
111+
/// .bottomModal(
112+
/// isPresented: $isModalPresented,
113+
/// model: BottomModalVM(),
114+
/// onDismiss: {
115+
/// print("Modal dismissed")
116+
/// },
117+
/// header: {
118+
/// Text("Header")
119+
/// },
120+
/// body: {
121+
/// Text("Body content goes here")
122+
/// },
123+
/// footer: {
124+
/// SUButton(model: .init {
125+
/// $0.title = "Close"
126+
/// }) {
127+
/// isModalPresented = false
128+
/// }
129+
/// }
130+
/// )
131+
/// ```
93132
public func bottomModal<Header: View, Body: View, Footer: View>(
94133
isPresented: Binding<Bool>,
95134
model: BottomModalVM = .init(),
@@ -116,6 +155,67 @@ extension View {
116155
}
117156

118157
extension View {
158+
/// A SwiftUI view modifier that presents a bottom-aligned modal bound to an optional identifiable item.
159+
///
160+
/// This modifier allows you to attach a modal to any SwiftUI view, which is displayed when the `item` binding
161+
/// is non-`nil`. The modal content is dynamically generated based on the unwrapped `Item`.
162+
///
163+
/// - Parameters:
164+
/// - item: A binding to an optional `Item` that determines whether the modal is presented.
165+
/// When `item` is `nil`, the modal is hidden.
166+
/// - model: A model that defines the appearance properties.
167+
/// - onDismiss: An optional closure executed when the modal is dismissed. Defaults to `nil`.
168+
/// - header: A closure that provides the view for the modal's header, based on the unwrapped `Item`.
169+
/// - body: A closure that provides the view for the modal's main content, based on the unwrapped `Item`.
170+
/// - footer: A closure that provides the view for the modal's footer, based on the unwrapped `Item`.
171+
///
172+
/// - Returns: A modified `View` with a bottom modal attached.
173+
///
174+
/// - Example:
175+
/// ```swift
176+
/// struct ContentView: View {
177+
/// struct ModalData: Identifiable {
178+
/// var id: String {
179+
/// return text
180+
/// }
181+
/// let text: String
182+
/// }
183+
///
184+
/// @State private var selectedItem: ModalData?
185+
/// private let items: [ModalData] = [
186+
/// ModalData(text: "data 1"),
187+
/// ModalData(text: "data 2")
188+
/// ]
189+
///
190+
/// var body: some View {
191+
/// List(items) { item in
192+
/// Button("Show Modal") {
193+
/// selectedItem = item
194+
/// }
195+
/// }
196+
/// .bottomModal(
197+
/// item: $selectedItem,
198+
/// model: BottomModalVM(),
199+
/// onDismiss: {
200+
/// print("Modal dismissed")
201+
/// },
202+
/// header: { item in
203+
/// Text("Header for \(item.text)")
204+
/// },
205+
/// body: { item in
206+
/// Text("Body content for \(item.text)")
207+
/// },
208+
/// footer: { _ in
209+
/// SUButton(model: .init {
210+
/// $0.title = "Close"
211+
/// }) {
212+
/// selectedItem = nil
213+
/// }
214+
/// }
215+
/// )
216+
/// }
217+
/// }
218+
/// ```
119219
public func bottomModal<Item: Identifiable, Header: View, Body: View, Footer: View>(
120220
item: Binding<Item?>,
121221
model: BottomModalVM = .init(),
@@ -151,6 +251,55 @@ extension View {
151251
)
152252
}
153253

254+
/// A SwiftUI view modifier that presents a bottom-aligned modal bound to an optional identifiable item.
255+
///
256+
/// This modifier allows you to attach a modal to any SwiftUI view, which is displayed when the `item` binding
257+
/// is non-`nil`. The modal content is dynamically generated based on the unwrapped `Item`.
258+
///
259+
/// - Parameters:
260+
/// - item: A binding to an optional `Item` that determines whether the modal is presented.
261+
/// When `item` is `nil`, the modal is hidden.
262+
/// - model: A model that defines the appearance properties.
263+
/// - onDismiss: An optional closure executed when the modal is dismissed. Defaults to `nil`.
264+
/// - body: A closure that provides the view for the modal's main content, based on the unwrapped `Item`.
265+
///
266+
/// - Returns: A modified `View` with a bottom modal attached.
267+
///
268+
/// - Example:
269+
/// ```swift
270+
/// struct ContentView: View {
271+
/// struct ModalData: Identifiable {
272+
/// var id: String {
273+
/// return text
274+
/// }
275+
/// let text: String
276+
/// }
277+
///
278+
/// @State private var selectedItem: ModalData?
279+
/// private let items: [ModalData] = [
280+
/// ModalData(text: "data 1"),
281+
/// ModalData(text: "data 2")
282+
/// ]
283+
///
284+
/// var body: some View {
285+
/// List(items) { item in
286+
/// Button("Show Modal") {
287+
/// selectedItem = item
288+
/// }
289+
/// }
290+
/// .bottomModal(
291+
/// item: $selectedItem,
292+
/// model: BottomModalVM(),
293+
/// onDismiss: {
294+
/// print("Modal dismissed")
295+
/// },
296+
/// body: { item in
297+
/// Text("Body content for \(item.text)")
298+
/// }
299+
/// )
300+
/// }
301+
/// }
302+
/// ```
154303
public func bottomModal<Item: Identifiable, Body: View>(
155304
item: Binding<Item?>,
156305
model: BottomModalVM = .init(),

Sources/ComponentsKit/Modal/SwiftUI/SUCenterModal.swift

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,45 @@ struct SUCenterModal<Header: View, Body: View, Footer: View>: View {
5252
// MARK: - Presentation Helpers
5353

5454
extension View {
55+
/// A SwiftUI view modifier that presents a center-aligned modal.
56+
///
57+
/// This modifier allows you to attach a cetner modal to any SwiftUI view, providing a structured way to display modals
58+
/// with a header, body, and footer, all styled and laid out according to the provided `CenterModalVM` model.
59+
///
60+
/// - Parameters:
61+
/// - isPresented: A binding that determines whether the modal is presented.
62+
/// - model: A model that defines the appearance properties.
63+
/// - onDismiss: An optional closure executed when the modal is dismissed.
64+
/// - header: A closure that provides the view for the modal's header.
65+
/// - body: A closure that provides the view for the modal's main content.
66+
/// - footer: A closure that provides the view for the modal's footer.
67+
///
68+
/// - Returns: A modified `View` with a center modal attached.
69+
///
70+
/// - Example:
71+
/// ```swift
72+
/// SomeView()
73+
/// .centerModal(
74+
/// isPresented: $isModalPresented,
75+
/// model: CenterModalVM(),
76+
/// onDismiss: {
77+
/// print("Modal dismissed")
78+
/// },
79+
/// header: {
80+
/// Text("Header")
81+
/// },
82+
/// body: {
83+
/// Text("Body content goes here")
84+
/// },
85+
/// footer: {
86+
/// SUButton(model: .init {
87+
/// $0.title = "Close"
88+
/// }) {
89+
/// isModalPresented = false
90+
/// }
91+
/// }
92+
/// )
93+
/// ```
5594
public func centerModal<Header: View, Body: View, Footer: View>(
5695
isPresented: Binding<Bool>,
5796
model: CenterModalVM = .init(),
@@ -78,6 +117,67 @@ extension View {
78117
}
79118

80119
extension View {
120+
/// A SwiftUI view modifier that presents a center-aligned modal bound to an optional identifiable item.
121+
///
122+
/// This modifier allows you to attach a modal to any SwiftUI view, which is displayed when the `item` binding
123+
/// is non-`nil`. The modal content is dynamically generated based on the unwrapped `Item`.
124+
///
125+
/// - Parameters:
126+
/// - item: A binding to an optional `Item` that determines whether the modal is presented.
127+
/// When `item` is `nil`, the modal is hidden.
128+
/// - model: A model that defines the appearance properties.
129+
/// - onDismiss: An optional closure executed when the modal is dismissed. Defaults to `nil`.
130+
/// - header: A closure that provides the view for the modal's header, based on the unwrapped `Item`.
131+
/// - body: A closure that provides the view for the modal's main content, based on the unwrapped `Item`.
132+
/// - footer: A closure that provides the view for the modal's footer, based on the unwrapped `Item`.
133+
///
134+
/// - Returns: A modified `View` with a center modal attached.
135+
///
136+
/// - Example:
137+
/// ```swift
138+
/// struct ContentView: View {
139+
/// struct ModalData: Identifiable {
140+
/// var id: String {
141+
/// return text
142+
/// }
143+
/// let text: String
144+
/// }
145+
///
146+
/// @State private var selectedItem: ModalData?
147+
/// private let items: [ModalData] = [
148+
/// ModalData(text: "data 1"),
149+
/// ModalData(text: "data 2")
150+
/// ]
151+
///
152+
/// var body: some View {
153+
/// List(items) { item in
154+
/// Button("Show Modal") {
155+
/// selectedItem = item
156+
/// }
157+
/// }
158+
/// .centerModal(
159+
/// item: $selectedItem,
160+
/// model: CenterModalVM(),
161+
/// onDismiss: {
162+
/// print("Modal dismissed")
163+
/// },
164+
/// header: { item in
165+
/// Text("Header for \(item.text)")
166+
/// },
167+
/// body: { item in
168+
/// Text("Body content for \(item.text)")
169+
/// },
170+
/// footer: { _ in
171+
/// SUButton(model: .init {
172+
/// $0.title = "Close"
173+
/// }) {
174+
/// selectedItem = nil
175+
/// }
176+
/// }
177+
/// )
178+
/// }
179+
/// }
180+
/// ```
81181
public func centerModal<Item: Identifiable, Header: View, Body: View, Footer: View>(
82182
item: Binding<Item?>,
83183
model: CenterModalVM = .init(),
@@ -113,6 +213,55 @@ extension View {
113213
)
114214
}
115215

216+
/// A SwiftUI view modifier that presents a center-aligned modal bound to an optional identifiable item.
217+
///
218+
/// This modifier allows you to attach a modal to any SwiftUI view, which is displayed when the `item` binding
219+
/// is non-`nil`. The modal content is dynamically generated based on the unwrapped `Item`.
220+
///
221+
/// - Parameters:
222+
/// - item: A binding to an optional `Item` that determines whether the modal is presented.
223+
/// When `item` is `nil`, the modal is hidden.
224+
/// - model: A model that defines the appearance properties.
225+
/// - onDismiss: An optional closure executed when the modal is dismissed. Defaults to `nil`.
226+
/// - body: A closure that provides the view for the modal's main content, based on the unwrapped `Item`.
227+
///
228+
/// - Returns: A modified `View` with a center modal attached.
229+
///
230+
/// - Example:
231+
/// ```swift
232+
/// struct ContentView: View {
233+
/// struct ModalData: Identifiable {
234+
/// var id: String {
235+
/// return text
236+
/// }
237+
/// let text: String
238+
/// }
239+
///
240+
/// @State private var selectedItem: ModalData?
241+
/// private let items: [ModalData] = [
242+
/// ModalData(text: "data 1"),
243+
/// ModalData(text: "data 2")
244+
/// ]
245+
///
246+
/// var body: some View {
247+
/// List(items) { item in
248+
/// Button("Show Modal") {
249+
/// selectedItem = item
250+
/// }
251+
/// }
252+
/// .centerModal(
253+
/// item: $selectedItem,
254+
/// model: CenterModalVM(),
255+
/// onDismiss: {
256+
/// print("Modal dismissed")
257+
/// },
258+
/// body: { item in
259+
/// Text("Body content for \(item.text)")
260+
/// }
261+
/// )
262+
/// }
263+
/// }
264+
/// ```
116265
public func centerModal<Item: Identifiable, Body: View>(
117266
item: Binding<Item?>,
118267
model: CenterModalVM = .init(),

0 commit comments

Comments
 (0)