Keyboard dismissal fixes #12

Merged
javier merged 2 commits from app/fix-calendar into main 2026-02-12 10:48:11 +00:00
2 changed files with 25 additions and 50 deletions
Showing only changes of commit db658a52c6 - Show all commits
@@ -1,43 +0,0 @@
import SwiftUI
/// A view modifier that resigns the first responder status when the view is tapped.
///
/// This modifier is useful for dismissing the keyboard or other input controls
/// when the user taps on an area of the view that doesn't have interactive content.
struct ResignFocusModifier: ViewModifier {
// MARK: Body
/// The content and behavior of the view modifier.
///
/// Adds a tap gesture that sends the `resignFirstResponder` action
/// to dismiss any active first responder (such as a text field).
func body(content: Content) -> some View {
content
.onTapGesture {
UIApplication.shared.sendAction(
#selector(UIResponder.resignFirstResponder),
to: nil,
from: nil,
for: nil
)
}
}
}
// MARK: - View Extension
extension View {
/// Adds a tap gesture that resigns the first responder when the view is tapped.
///
/// This is useful for dismissing the keyboard or other input controls
/// when the user taps outside of an interactive element.
///
/// - Returns: A view that resigns first responder status on tap.
func onResignFocus() -> some View {
modifier(ResignFocusModifier())
}
}
@@ -8,12 +8,6 @@ extension TaskListView {
/// This view is responsible for querying and displaying the list of tasks based on the specified
/// group and completion status filter. It exists as a separate view to enable dynamic query
/// updates when filter parameters change.
///
/// Task reordering is enabled based on the ``TodoGroup/canReorder`` property.
/// Groups that support reordering (``TodoGroup/today``, ``TodoGroup/upcoming``,
/// ``TodoGroup/overdue``) allow users to drag and drop tasks to change their order.
/// The ``TodoGroup/completed`` group does not support reordering as tasks are
/// displayed in chronological order by completion date.
struct Content: View {
// MARK: Type aliases
@@ -124,7 +118,9 @@ extension TaskListView {
items
}
.listStyle(.grouped)
.onResignFocus()
.onTapGesture {
resignFocus()
}
}
}
}
@@ -139,6 +135,12 @@ private extension TaskListView.Content {
// MARK: Computed
/// A view that renders the task items with appropriate modifiers.
///
/// This computed property constructs a `ForEach` view over the tasks and conditionally
/// applies the `.onMove` modifier based on the `canReorder` capability. This approach
/// ensures that:
/// - All todo task lists support swipe-to-delete via `.onDelete`
/// - Only todo task groups that can be manually reordered enable drag-and-drop via `.onMove`
@ViewBuilder
var items: some View {
let items = ForEach(todos) {
@@ -158,6 +160,22 @@ private extension TaskListView.Content {
}
}
// MARK: Functions
/// Dismisses the keyboard by resigning first responder status.
///
/// This function sends a `resignFirstResponder` action through the responder chain,
/// causing any active text field or text view to resign its first responder status
/// and dismiss the keyboard.
func resignFocus() {
UIApplication.shared.sendAction(
#selector(UIResponder.resignFirstResponder),
to: nil,
from: nil,
for: nil
)
}
}
// MARK: - Previews