Files
todos/App/Sources/View Modifiers/NewTaskButtonModifier.swift
javier dd6f453466 App layout improvements (#10)
This PR contains the work done to improve the app layout for max iPhones and iPads by levering on the navigation split view. Plus, the floating button to add todo tasks was improved and integrated better into the layout and a critical bug occurring on max iPhones and iPads was fixed.

Reviewed-on: rock-n-code/todos-app#10
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
2026-02-12 03:55:17 +00:00

99 lines
2.7 KiB
Swift

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