fix(store): replace ZStack overlay sticky approach with native pinnedViews + reliable scroll tracking
- Use LazyVStack(pinnedViews: [.sectionHeaders]) for native section header stickiness - Move ScrollOffsetReader outside LazyVStack (sibling) to prevent lazy-unload breaking scroll tracking - Add baseline capture to ScrollOffsetReader to correctly normalize offset regardless of ScrollView content insets - Apply safeAreaTop padding to categoryTabs only when pinned (isCategoryTabsPinned), preventing oversized header before scroll - Remove complex ZStack dual-tabs overlay, stickyProgress logic, and categoryTabsStickyProgress - categoryTabs now accepts isPinned flag with easeInOut(0.15s) animation on pin transition Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -195,10 +195,15 @@ extension StoreDetailView {
|
||||
}
|
||||
}
|
||||
|
||||
func categoryTabs(proxy: ScrollViewProxy, topExtension: CGFloat = 0, stickyProgress: CGFloat = 0) -> some View {
|
||||
let chipPaddingH: CGFloat = 10 + 6 * stickyProgress
|
||||
let chipPaddingV: CGFloat = 4 + 5 * stickyProgress
|
||||
let containerPaddingV: CGFloat = 2 + 8 * stickyProgress
|
||||
func categoryTabs(proxy: ScrollViewProxy, isPinned: Bool = false) -> some View {
|
||||
let safeTop: CGFloat = {
|
||||
guard isPinned else { return 0 }
|
||||
#if canImport(UIKit)
|
||||
return UIDevice.appSafeAreaTop
|
||||
#else
|
||||
return 0
|
||||
#endif
|
||||
}()
|
||||
|
||||
return ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(spacing: 10) {
|
||||
@@ -217,8 +222,8 @@ extension StoreDetailView {
|
||||
Text(category.name)
|
||||
.font(AppTypography.heading3)
|
||||
.foregroundStyle(active ? AppColors.textInverse : AppColors.textMuted)
|
||||
.padding(.horizontal, chipPaddingH)
|
||||
.padding(.vertical, chipPaddingV)
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.vertical, 9)
|
||||
.background(active ? AppColors.primary : AppColors.surface)
|
||||
.clipShape(Capsule())
|
||||
}
|
||||
@@ -226,16 +231,11 @@ extension StoreDetailView {
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.vertical, containerPaddingV)
|
||||
.padding(.vertical, 10)
|
||||
}
|
||||
.padding(.top, safeTop)
|
||||
.background(AppColors.backgroundLight)
|
||||
.overlay(alignment: .top) {
|
||||
AppColors.backgroundLight
|
||||
.frame(height: topExtension)
|
||||
.frame(maxWidth: .infinity)
|
||||
.offset(y: -topExtension)
|
||||
.allowsHitTesting(false)
|
||||
}
|
||||
.animation(.easeInOut(duration: 0.15), value: isPinned)
|
||||
}
|
||||
|
||||
func productCard(_ item: StoreCatalogListItem, in category: StoreCatalogCategory) -> some View {
|
||||
|
||||
Reference in New Issue
Block a user