Task edition improvements (#9)
This PR contains the work done to improve upon the editing experience on the **Task list item and the **New task** views. Reviewed-on: rock-n-code/todos-app#9 Co-authored-by: Javier Cicchelli <javier@rock-n-code.com> Co-committed-by: Javier Cicchelli <javier@rock-n-code.com>
This commit was merged in pull request #9.
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
import SwiftUI
|
||||
|
||||
/// A view modifier that intercepts newlines in a text field and transfers focus to another field.
|
||||
///
|
||||
/// This modifier monitors text changes in a `TextField` component and prevents newlines
|
||||
/// from being added. Instead, when a newline is detected, it updates the focus state to move to
|
||||
/// a specified field.
|
||||
struct OnNewlineFocusModifier<Field: Hashable>: ViewModifier {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// Binding to the text being edited.
|
||||
@Binding
|
||||
private var text: String
|
||||
|
||||
/// Binding to the focus state.
|
||||
private let focusState: FocusState<Field?>.Binding
|
||||
|
||||
/// The field to focus when a newline is detected.
|
||||
private let targetField: Field
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Creates a modifier that transfers focus on newline.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - text: A binding to the text being edited.
|
||||
/// - focusState: A binding to the focus state.
|
||||
/// - targetField: The field to focus when a newline is detected.
|
||||
init(
|
||||
text: Binding<String>,
|
||||
focusState: FocusState<Field?>.Binding,
|
||||
targetField: Field
|
||||
) {
|
||||
self._text = text
|
||||
|
||||
self.focusState = focusState
|
||||
self.targetField = targetField
|
||||
}
|
||||
|
||||
// MARK: Body
|
||||
|
||||
/// The content and behavior of the view modifier.
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.onChange(of: text) { oldValue, newValue in
|
||||
guard newValue.contains(.newline) else {
|
||||
return
|
||||
}
|
||||
|
||||
text = oldValue
|
||||
focusState.wrappedValue = targetField
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - View Extension
|
||||
|
||||
extension View {
|
||||
|
||||
/// Transfers focus to another field when the user presses return in a text field.
|
||||
///
|
||||
/// This modifier prevents newlines from being added and instead moves keyboard focus
|
||||
/// to the specified field. Useful for creating a form-like flow between text fields.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - text: A binding to the text being edited.
|
||||
/// - field: The field to focus when return is pressed.
|
||||
/// - focusState: A binding to the focus state.
|
||||
/// - Returns: A modified view with focus transfer behavior.
|
||||
func onNewlineFocus<Field: Hashable>(
|
||||
_ text: Binding<String>,
|
||||
to field: Field,
|
||||
on focusState: FocusState<Field?>.Binding
|
||||
) -> some View {
|
||||
modifier(
|
||||
OnNewlineFocusModifier(
|
||||
text: text,
|
||||
focusState: focusState,
|
||||
targetField: field
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user