Rundes Such-Icon (40×40, .circle) als fester Anker rechts in einer Bottom-Filter-Leiste — Einstieg in die native .searchable(isPresented:)- Suche, Platzierung wie Apple Podcasts. iOS 26: echtes glassEffect, sonst Material-Kreis mit Hairline. Farbe aus @Environment(\.manaTheme), keine Farb-Parameter (analog ManaPill). Aus seepuls-native geliftet, Adoption in comicello + zitare folgt. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
63 lines
2.3 KiB
Swift
63 lines
2.3 KiB
Swift
import ManaTokens
|
||
import SwiftUI
|
||
|
||
/// Rundes Such-Icon für die Bottom-Filter-Leiste — Einstieg in die
|
||
/// *native* Suche (`.searchable(text:isPresented:)`). Gedacht als fester
|
||
/// Anker **rechts** in einer Filter-Leiste (außerhalb des horizontalen
|
||
/// Pill-Scrollers), Platzierung wie die System-Suche in der Apple-
|
||
/// Podcasts-App. Referenz-Adoption: seepuls-Events/Orte-Tab.
|
||
///
|
||
/// Form & Größe sind hier zentral festgelegt (40×40, `.circle`), damit das
|
||
/// Icon über die Flotte gleich aussieht. Farbe kommt aus der aktiven
|
||
/// Theme-Variant via `@Environment(\.manaTheme)` — keine Farb-Parameter,
|
||
/// analog zu ``ManaPill``.
|
||
///
|
||
/// **iOS 26:** echtes Liquid-Glass (`glassEffect`). **iOS 18–25:**
|
||
/// Material-Kreis mit Hairline — konsistent mit den Filter-Leisten-Gläsern.
|
||
///
|
||
/// ```swift
|
||
/// // In der Filter-Leiste, rechts neben dem Pill-Scroller:
|
||
/// HStack {
|
||
/// ScrollView(.horizontal) { /* Filter-Pills */ }
|
||
/// ManaSearchButton { searchPresented = true }
|
||
/// }
|
||
/// // dazu am Screen: .searchable(text: $q, isPresented: $searchPresented)
|
||
/// ```
|
||
public struct ManaSearchButton: View {
|
||
@Environment(\.manaTheme) private var theme
|
||
|
||
private let action: () -> Void
|
||
|
||
/// - Parameter action: Tap-Handler — typischerweise `isPresented = true`,
|
||
/// das den `.searchable`-Modifier öffnet.
|
||
public init(action: @escaping () -> Void) {
|
||
self.action = action
|
||
}
|
||
|
||
public var body: some View {
|
||
Button(action: action) {
|
||
Image(systemName: "magnifyingglass")
|
||
.font(.system(size: 17, weight: .semibold))
|
||
.foregroundStyle(theme.colors.primary)
|
||
.frame(width: 40, height: 40)
|
||
.modifier(SearchButtonBackground(border: theme.colors.border))
|
||
}
|
||
.buttonStyle(.plain)
|
||
.accessibilityLabel("Suchen")
|
||
}
|
||
}
|
||
|
||
/// iOS 26: Liquid-Glass-Kreis. Fallback: Material-Kreis mit Hairline.
|
||
private struct SearchButtonBackground: ViewModifier {
|
||
let border: Color
|
||
|
||
func body(content: Content) -> some View {
|
||
if #available(iOS 26, macOS 26, *) {
|
||
content.glassEffect(.regular.interactive(), in: .circle)
|
||
} else {
|
||
content
|
||
.background(.ultraThinMaterial, in: .circle)
|
||
.overlay(Circle().stroke(border, lineWidth: 0.5))
|
||
}
|
||
}
|
||
}
|