feat(store): stretch cover image on pull-down overscroll

- Remove max(0) clamp in ScrollOffsetReader to allow negative values during bounce
- Add stretchAmount computed var (max(0, -scrollOffset))
- Hero image frame grows by stretchAmount and offsets upward on overscroll
- isCategoryTabsPinned still uses max(0, scrollOffset) via >= check
This commit is contained in:
Daniel Arantes Loverde
2026-06-03 15:01:23 -03:00
parent f51319b486
commit d2189bb701
3 changed files with 4 additions and 2 deletions

View File

@@ -37,7 +37,7 @@ struct ScrollOffsetReader: View {
)
.onPreferenceChange(ScrollOffsetPreferenceKey.self) { minY in
if baseline == nil { baseline = minY }
let offset = max(0, (baseline ?? 0) - minY)
let offset = (baseline ?? 0) - minY
if abs(offsetY - offset) > 0.5 {
offsetY = offset
}

View File

@@ -26,7 +26,7 @@ extension StoreDetailView {
var heroSection: some View {
ZStack(alignment: .top) {
AsyncStoreImage(imageURL: resolvedURL(storeCoverURL))
.frame(height: topSectionHeight)
.frame(height: topSectionHeight + stretchAmount)
.overlay(
LinearGradient(
colors: [Color.black.opacity(0.32), Color.black.opacity(0.05)],
@@ -34,6 +34,7 @@ extension StoreDetailView {
endPoint: .bottom
)
)
.offset(y: -stretchAmount)
.ignoresSafeArea(.container, edges: .top)
VStack(spacing: 0) {

View File

@@ -38,6 +38,7 @@ struct StoreDetailView: View {
@State var scrollOffset: CGFloat = 0
var isCategoryTabsPinned: Bool { scrollOffset >= topSectionHeight }
var stretchAmount: CGFloat { max(0, -scrollOffset) }
let cardTopInset: CGFloat = 180
let summaryCardBaseHeight: CGFloat = 212