diff --git a/MacApp/Relay/Welcome/WelcomeView.swift b/MacApp/Relay/Welcome/WelcomeView.swift index 2b5f1e5..5ae6eea 100644 --- a/MacApp/Relay/Welcome/WelcomeView.swift +++ b/MacApp/Relay/Welcome/WelcomeView.swift @@ -80,8 +80,45 @@ struct WelcomeView: View { Divider() + // Search field + HStack(spacing: 8) { + Image(systemName: "magnifyingglass") + .foregroundStyle(.tertiary) + .accessibilityHidden(true) + + TextField( + "Search projects…", + text: Binding( + get: { store.searchText }, + set: { store.send(.searchTextChanged($0)) } + ) + ) + .textFieldStyle(.plain) + .accessibilityLabel("Search projects by name or path") + + if !store.searchText.isEmpty { + Button(action: clearSearch) { + Image(systemName: "xmark.circle.fill") + .foregroundStyle(.tertiary) + } + .buttonStyle(.plain) + .accessibilityLabel("Clear search") + .accessibilityAddTraits(.isButton) + } + } + .padding(.horizontal, 12) + .padding(.vertical, 8) + .background(Color(nsColor: .controlBackgroundColor)) + .cornerRadius(6) + .padding(.horizontal, 16) + .padding(.vertical, 12) + + Divider() + if store.recentProjects.isEmpty { emptyState + } else if store.filteredProjects.isEmpty && !store.searchText.isEmpty { + noSearchResultsState } else { projectsList } @@ -110,6 +147,27 @@ struct WelcomeView: View { .accessibilityLabel("No recent projects. Open a folder to get started.") } + // MARK: - No search results state + + private var noSearchResultsState: some View { + VStack(spacing: 12) { + Spacer() + Image(systemName: "magnifyingglass") + .font(.system(size: 40)) + .foregroundStyle(.tertiary) + .accessibilityHidden(true) + Text("No Matching Projects") + .font(.title3) + .foregroundStyle(.secondary) + Text("Try a different search term.") + .font(.subheadline) + .foregroundStyle(.tertiary) + Spacer() + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .accessibilityLabel("No projects matching your search.") + } + // MARK: - Projects list private var projectsList: some View { @@ -190,6 +248,10 @@ struct WelcomeView: View { private func deleteProject(_ project: ProjectInfo) { store.send(.removeRecent(URL(filePath: project.path))) } + + private func clearSearch() { + store.send(.searchTextChanged("")) + } } // MARK: - RecentProjectRow