Improve search field layout and responsiveness

SearchTextField improvements:
- Add flexible width constraints (minWidth: 250, maxWidth: .infinity) for macOS
- Restructure iOS layout to use HStack instead of ZStack for better alignment
- Add invisible spacer to maintain consistent width when clear button is hidden
- Adjust padding for more balanced appearance
- Remove fixed width from fieldBorder to support flexible sizing

SearchView improvements:
- Wrap in GeometryReader to calculate available width dynamically
- Add searchFieldWidth() helper to compute optimal search field width
- Account for navigation buttons and internal padding
- Apply dynamic width to both FocusableSearchTextField and SearchTextField

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Arkadiusz Fal
2025-11-09 14:05:07 +01:00
parent 62d5a86146
commit 73d9581449
2 changed files with 81 additions and 55 deletions

View File

@@ -40,16 +40,15 @@ struct SearchTextField: View {
} }
} }
} }
.frame(minWidth: 250, idealWidth: 300, maxWidth: .infinity)
.transaction { t in t.animation = nil } .transaction { t in t.animation = nil }
} }
#else #else
var body: some View { var body: some View {
ZStack {
HStack {
HStack(spacing: 0) { HStack(spacing: 0) {
Image(systemName: "magnifyingglass") Image(systemName: "magnifyingglass")
.foregroundColor(.gray) .foregroundColor(.gray)
.padding(.leading, 5) .padding(.leading, 8)
.padding(.trailing, 5) .padding(.trailing, 5)
.imageScale(.medium) .imageScale(.medium)
@@ -67,7 +66,13 @@ struct SearchTextField: View {
if !state.queryText.isEmpty { if !state.queryText.isEmpty {
clearButton clearButton
.padding(.leading, 5) .padding(.leading, 5)
.padding(.trailing, 5) .padding(.trailing, 8)
} else {
// Invisible spacer to maintain consistent width
clearButton
.opacity(0)
.padding(.leading, 5)
.padding(.trailing, 8)
} }
} }
.background( .background(
@@ -78,10 +83,7 @@ struct SearchTextField: View {
RoundedRectangle(cornerRadius: 8) RoundedRectangle(cornerRadius: 8)
.stroke(Color(UIColor.secondarySystemBackground), lineWidth: 1) .stroke(Color(UIColor.secondarySystemBackground), lineWidth: 1)
) )
.frame(maxWidth: .infinity, alignment: .leading) .padding(.horizontal, 16)
}
.padding(.horizontal, 0)
}
.transaction { t in t.animation = nil } .transaction { t in t.animation = nil }
} }
#endif #endif
@@ -89,11 +91,11 @@ struct SearchTextField: View {
private var fieldBorder: some View { private var fieldBorder: some View {
RoundedRectangle(cornerRadius: 5, style: .continuous) RoundedRectangle(cornerRadius: 5, style: .continuous)
.fill(Color.background) .fill(Color.background)
.frame(width: 250, height: 27) .frame(height: 27)
.overlay( .overlay(
RoundedRectangle(cornerRadius: 5, style: .continuous) RoundedRectangle(cornerRadius: 5, style: .continuous)
.stroke(Color.gray.opacity(0.4), lineWidth: 1) .stroke(Color.gray.opacity(0.4), lineWidth: 1)
.frame(width: 250, height: 27) .frame(height: 27)
) )
} }

View File

@@ -41,6 +41,7 @@ struct SearchView: View {
#if os(iOS) #if os(iOS)
var body: some View { var body: some View {
GeometryReader { geometry in
VStack { VStack {
VStack { VStack {
if accounts.app.supportsSearchSuggestions, state.query.query != state.queryText { if accounts.app.supportsSearchSuggestions, state.query.query != state.queryText {
@@ -58,14 +59,17 @@ struct SearchView: View {
ToolbarItem(placement: .principal) { ToolbarItem(placement: .principal) {
if #available(iOS 15, *) { if #available(iOS 15, *) {
FocusableSearchTextField() FocusableSearchTextField()
.frame(width: searchFieldWidth(geometry.size.width))
} else { } else {
SearchTextField() SearchTextField()
.frame(width: searchFieldWidth(geometry.size.width))
} }
} }
ToolbarItem(placement: .navigationBarTrailing) { ToolbarItem(placement: .navigationBarTrailing) {
searchMenu searchMenu
} }
} }
}
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.ignoresSafeArea(.keyboard, edges: .bottom) .ignoresSafeArea(.keyboard, edges: .bottom)
.navigationTitle("Search") .navigationTitle("Search")
@@ -645,6 +649,26 @@ struct SearchView: View {
)) ))
} }
#if os(iOS)
private func searchFieldWidth(_ viewWidth: CGFloat) -> CGFloat {
// Base padding for internal SearchTextField padding (16pt each side = 32 total)
var totalDeduction: CGFloat = 32
// Add space for trailing menu button
totalDeduction += 44
// Add space for sidebar toggle button if in sidebar navigation style
if navigationStyle == .sidebar {
totalDeduction += 44
}
// Minimum width to ensure usability
let minWidth: CGFloat = 200
return max(minWidth, viewWidth - totalDeduction)
}
#endif
var shouldDisplayHeader: Bool { var shouldDisplayHeader: Bool {
#if os(tvOS) #if os(tvOS)
!state.query.isEmpty !state.query.isEmpty