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>
This commit was merged in pull request #10.
This commit is contained in:
2026-02-12 03:55:17 +00:00
committed by javier
parent 52376695a4
commit dd6f453466
9 changed files with 288 additions and 43 deletions
+49 -17
View File
@@ -12,12 +12,18 @@ struct TaskGroupListView: View {
// MARK: Properties
/// Binding to the currently selected todo task group.
///
/// When provided, the view will use this binding for navigation split view selection.
@Binding
private var group: TodoGroup?
/// Query to monitor all todo tasks for changes.
///
/// This query triggers view updates whenever todo tasks are inserted, updated, or deleted,
/// ensuring the task counts displayed in the view remain accurate.
@Query
private var tasks: [Todo]
private var todos: [Todo]
/// The view model managing the state and logic for this view.
///
@@ -26,6 +32,18 @@ struct TaskGroupListView: View {
@State
private var viewModel = ViewModel()
// MARK: Initializers
/// Creates a task group list view with a binding to the selected group.
///
/// This initializer configures the view for use in a navigation split view,
/// where the binding tracks which task group is currently selected in the sidebar.
///
/// - Parameter group: A binding to the currently selected task group.
init(_ group: Binding<TodoGroup?>) {
self._group = group
}
// MARK: Body
/// The content and behavior of the view.
@@ -35,24 +53,30 @@ struct TaskGroupListView: View {
/// - The group's title
/// - The current count of tasks in that group
///
/// Cards are tappable and navigate to a detailed task list for the selected group.
/// Cards are tappable and update the selected group binding for navigation split view.
/// Task counts are fetched on-demand from the model context for each render.
var body: some View {
ScrollView {
VStack(spacing: 16) {
ForEach(viewModel.groups) { group in
NavigationLink(destination: TaskListView(group: group)) {
Card(
group: group,
count: viewModel.count(tasks, for: group)
)
}
.buttonStyle(.plain)
}
}
.padding(.horizontal)
List(
viewModel.groups,
selection: $group
) { group in
Card(
group: group,
count: viewModel.count(
todos,
for: group
)
)
.listRowBackground(Color.clear)
.listRowSeparator(.hidden)
.tag(group)
}
.listStyle(.plain)
.navigationTitle("view.task-group-list.navigation.title")
.sensoryFeedback(
.selection,
trigger: group
)
}
}
@@ -62,8 +86,12 @@ struct TaskGroupListView: View {
"Task group list with empty tasks",
traits: .emptyContainer
) {
@Previewable
@State
var group: TodoGroup?
NavigationStack {
TaskGroupListView()
TaskGroupListView($group)
}
}
@@ -71,7 +99,11 @@ struct TaskGroupListView: View {
"Task group list with sample tasks",
traits: .sampleTasks
) {
@Previewable
@State
var group: TodoGroup?
NavigationStack {
TaskGroupListView()
TaskGroupListView($group)
}
}