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:
Daniel Arantes Loverde
2026-06-03 14:26:23 -03:00
parent b61f59c253
commit 69dd67b8a5
4 changed files with 37 additions and 65 deletions

View File

@@ -22,6 +22,7 @@ struct ScrollOffsetPreferenceKey: PreferenceKey {
struct ScrollOffsetReader: View {
@Binding var offsetY: CGFloat
@State private var baseline: CGFloat? = nil
var body: some View {
Color.clear
@@ -35,9 +36,10 @@ struct ScrollOffsetReader: View {
}
)
.onPreferenceChange(ScrollOffsetPreferenceKey.self) { minY in
let normalizedOffset = max(0, -minY)
if abs(offsetY - normalizedOffset) > 0.5 {
offsetY = normalizedOffset
if baseline == nil { baseline = minY }
let offset = max(0, (baseline ?? 0) - minY)
if abs(offsetY - offset) > 0.5 {
offsetY = offset
}
}
}