App layout improvements #10
@@ -0,0 +1,98 @@
|
||||
import SwiftUI
|
||||
|
||||
/// A view modifier that adds a floating action button for creating new tasks.
|
||||
///
|
||||
/// This modifier overlays a glass-effect button in the bottom-trailing corner of the view.
|
||||
/// The button can be conditionally shown or hidden with smooth animations.
|
||||
struct NewTaskButtonModifier: ViewModifier {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// Whether the floating button should be displayed.
|
||||
let showButton: Bool
|
||||
|
||||
/// The action to perform when the button is tapped.
|
||||
let action: () -> Void
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
/// Applies the floating action button to the content view.
|
||||
///
|
||||
/// When `showButton` is true, overlays a blue glass-effect button with a plus icon
|
||||
/// in the bottom-trailing corner. The button animates in/out with opacity and scale transitions,
|
||||
/// and includes a spring animation when pressed.
|
||||
///
|
||||
/// - Parameter content: The view to which the button will be added.
|
||||
/// - Returns: The modified view with the floating button overlay.
|
||||
func body(content: Content) -> some View {
|
||||
ZStack(alignment: .bottomTrailing) {
|
||||
content
|
||||
|
||||
if showButton {
|
||||
Button(action: action) {
|
||||
Image(systemName: "plus")
|
||||
.frame(width: 48, height: 48)
|
||||
.foregroundStyle(.white)
|
||||
}
|
||||
.glassEffect(.regular.tint(.blue.opacity(0.8)).interactive())
|
||||
.padding(.trailing, 20)
|
||||
}
|
||||
}
|
||||
.animation(
|
||||
.spring(response: 0.4, dampingFraction: 0.8),
|
||||
value: showButton
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - View Extension
|
||||
|
||||
extension View {
|
||||
|
||||
/// Adds a floating action button for creating new tasks.
|
||||
///
|
||||
/// This convenience method applies the ``NewTaskButtonModifier`` to show a glass-effect
|
||||
/// button in the bottom-trailing corner of the view.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - show: Whether the floating button should be displayed.
|
||||
/// - action: The action to perform when the button is tapped.
|
||||
/// - Returns: The modified view with the floating button overlay.
|
||||
func newTaskButton(
|
||||
show: Bool,
|
||||
action: @escaping () -> Void
|
||||
) -> some View {
|
||||
modifier(
|
||||
NewTaskButtonModifier(
|
||||
showButton: show,
|
||||
action: action
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
// MARK: - Previews
|
||||
|
||||
#Preview("New Task Button") {
|
||||
@Previewable
|
||||
@State
|
||||
var showButton = true
|
||||
|
||||
VStack {
|
||||
Spacer()
|
||||
Toggle(
|
||||
"Show Button",
|
||||
isOn: $showButton
|
||||
)
|
||||
Spacer()
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.frame(
|
||||
maxWidth: .infinity,
|
||||
maxHeight: .infinity
|
||||
)
|
||||
.newTaskButton(show: showButton) {
|
||||
// On action closure.
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user