diff --git a/FuelBoard/StationsView.swift b/FuelBoard/StationsView.swift index 75333b7..4a693ca 100644 --- a/FuelBoard/StationsView.swift +++ b/FuelBoard/StationsView.swift @@ -22,10 +22,37 @@ struct StationsView: View { /// which station is "best". @State private var pageSize = 10 @State private var visibleCount = 10 + /// True once the list has scrolled — the large header title is shown at + /// rest; the compact gas-pump+title bar appears only after scrolling. + @State private var isScrolled = false var body: some View { NavigationStack { List { + // Large title header (icon + title). Native navigation titles + // can't carry an icon, so this is a real row; the scroll + // tracker rides on its background so no extra row is created. + HStack(spacing: 10) { + Image(systemName: "fuelpump.fill") + .font(.system(size: 34)) + .foregroundStyle(selectedFuel.tintColor) + Text("FuelBoard") + .font(.largeTitle.bold()) + } + .frame(maxWidth: .infinity, alignment: .leading) + .padding(.vertical, 6) + .listRowSeparator(.hidden) + .listRowInsets(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16)) + .listRowBackground(Color.clear) + .background( + GeometryReader { proxy in + Color.clear.preference( + key: ScrollOffsetKey.self, + value: proxy.frame(in: .named("stationsScroll")).minY + ) + } + ) + Section { if let location { if sortMode == .closest { @@ -180,24 +207,40 @@ struct StationsView: View { // New fetch or filter switch → back to the first page. visibleCount = pageSize } + .coordinateSpace(name: "stationsScroll") + .onPreferenceChange(ScrollOffsetKey.self) { minY in + isScrolled = minY < -60 + } .toolbar { ToolbarItem(placement: .principal) { - HStack(spacing: 6) { - Image(systemName: "fuelpump.fill") - .foregroundStyle(selectedFuel.tintColor) - Text("FuelBoard") - .font(.headline) + if isScrolled { + HStack(spacing: 6) { + Image(systemName: "fuelpump.fill") + .foregroundStyle(selectedFuel.tintColor) + Text("FuelBoard") + .font(.headline) + } + .transition(.opacity) } } } .navigationBarTitleDisplayMode(.inline) - .navigationTitle("FuelBoard") } } } // MARK: - Fuel-type iconography (app target only — FuelStore.swift is Foundation-only) +/// Scroll offset preference — the large-title header row reports its position +/// in the list's coordinate space so we know when it has scrolled under the +/// nav bar (minY < -60) and can show the compact gas-pump+title bar. +private struct ScrollOffsetKey: PreferenceKey { + static var defaultValue: CGFloat = 0 + static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { + value = nextValue() + } +} + extension FuelType { /// Short segment label ("Unleaded" / "Premium" / "Diesel") for the picker. var shortName: String {