SwiftUI Menu item misaligned vertically in an HStack

29 Views Asked by At

I've got an HStack with a Menu and a Link buttons, which are part of a card that pops up when the user clicks on the card's title. Every time the card expands fully, the Menu button is higher than the Link button. Once clicked, the Menu button goes down to its proper position.

Any ideas what I'm doing wrong?

struct ItemButtonRow: View {
    
    var item: ItemEntity
    var bottomPadding: CGFloat = 10
    @Binding var showShareSheet: Bool
    
    var body: some View {
        HStack(alignment: .center) {
            
            Menu(
                content: {
                    Button {
                        showShareSheet.toggle()
                    } label: {
                        Text("as image")
                        Image(systemName: "photo")
                    }

                    ShareLink(item: item.title, message: Text(item.summary)) {
                        Text("as text")
                        Image(systemName: "text.justify.left")
                    }
                },
                label: {
                    HStack {
                        Image(systemName: "square.and.arrow.up")
                        Text("Share")
                    }
                    .padding(10)
                    .background(RoundedRectangle(cornerRadius: 10).fill(Color("whitesand")))
                    .tint(Color(.secondaryLabel))
                }
            )
            
            Spacer()
            
            Link(destination: URL(string: "\(item.link)?utm_source=items&utm_medium=ios_app")!) {
                Image(systemName: "book")
                Text("Read more")
            }
            .padding(10)
            .background(RoundedRectangle(cornerRadius: 10).fill(Color("vpurple")))
            .tint(Color(.white))
            
        }
        .frame(height: 60)
        .padding(.bottom, bottomPadding)
    }
}

struct DailyItemView: View {

    @Environment(\.scenePhase) private var scenePhase
    @EnvironmentObject var am: ItemModel
    @EnvironmentObject var um: UnsplashModel

    @State private var cardPosition: BottomSheetPosition = .dynamicBottom
    @State private var showAboutScreen = false
    @State private var showShareSheet = false
    @State private var refreshImage = false
    
    private let haptics = UINotificationFeedbackGenerator()
    private let iPad = UIDevice.current.userInterfaceIdiom == .pad
    
    // MARK: - BODY
    var body: some View {
        
        let topCardPosition: BottomSheetPosition = iPad ? .relative(0.6) : .relative(0.8)
        
        ZStack {
            GeometryReader { proxy in
                DailyItemCoverImage(imageUrl: am.dailyItemCoverImageUrl, blurHash: am.dailyItemImageBlurHash)
            }
            .ignoresSafeArea()
            
            .bottomSheet(
                bottomSheetPosition: $cardPosition,
                switchablePositions: [.dynamicBottom, topCardPosition],
                headerContent: {
                    ItemTitle(item: am.dailyItem, showDate: false, alignment: .center)
                        .padding(.top, 20)
                        .padding(.horizontal, 25)
                        .padding(.horizontal, iPad ? 200 : 0)
                        .onTapGesture {
                            self.haptics.notificationOccurred(.success)
                            if cardPosition == .dynamicBottom {
                                cardPosition = topCardPosition
                            } else {
                                cardPosition = .dynamicBottom
                            }
                        }
                },
                mainContent: {
                    VStack {
                        ItemContentBox(item: am.dailyItem, scroll: true)
                        
                        ItemButtonRow(item: am.dailyItem, bottomPadding: 10, showShareSheet: $showShareSheet)
                    }
                    .padding(.top, 10)
                    .padding(.horizontal, 25)
                    .padding(.horizontal, iPad ? 200 : 0)
                }
            )
            .enableBackgroundBlur(cardPosition == topCardPosition ? true : false)
            .backgroundBlurMaterial(.dark(.thick))
            .showDragIndicator(true)
            .enableFlickThrough(false)
            .customBackground(
                HStack {
                    Spacer(minLength: iPad ? 150 : 0)
                    Color("background")
                        .opacity(0.95)
                        .cornerRadius(30, corners: [.topLeft, .topRight])
                        .shadow(color: .black.opacity(0.1), radius: 10, x:0, y: -2)
                    Spacer(minLength: iPad ? 150 : 0)
                }
            )
            .enableFloatingIPadSheet(false)
            .sheetWidth(iPad ? BottomSheetWidth.relative(1) : BottomSheetWidth.platformDefault)
        }
        .overlay(Color.black.opacity(showShareSheet ? 0.8 : 0))
        .animation(.easeInOut(duration: 0.2), value: showShareSheet)
        .sheet(isPresented: $showShareSheet) {
            ItemShare(item: am.dailyItem)
                .presentationDetents([.height(650)])
        }
        .toastDimmedBackground(true)
        // Refresh view when moving from a different screen
        .onAppear {
            print("DailyItemView: onAppear")
            am.getDailyItem()
        }
        // Refresh view when restoring from background
        .onChange(of: scenePhase) { newScene in
            switch newScene {
            case .active:
                print("Active scene")
                am.getDailyItem()
            case .inactive:
                print("Inactive scene")
                am.getDailyItem()
            case .background:
                print("Background scene")
            @unknown default:
                print("Unknown scene")
            }
        }
    }
}

Card expanded, Menu not clicked

Menu clicked

0

There are 0 best solutions below