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. } }