Mijick / PopupView

Popups presentation made simple (SwiftUI)
MIT License
1.19k stars 50 forks source link

TopPopup White Safe Area (See Screenshot) #37

Closed d42ohpaz closed 1 year ago

d42ohpaz commented 1 year ago

I created the following "alert" popup, and when it displays, the safe area at the top is white, despite my background being dark. I would expect any background to be using .clear by default. As a work around, I have implemented my own PopupConfig.

Screenshot 2023-06-01 at 8 08 44 AM
FulcrumOne commented 1 year ago

Hi @9ae8sdf76. Can you share your code regarding this example? I have just tested something similar and every time the view is correct, like on the image below. Probably there's some problem with your view hierarchy

IMG_B0F0320E577C-1

d42ohpaz commented 1 year ago

Sure. Here is my popup code:

import SwiftUI
import PopupView

enum AlertType {
    case success
    case warning
    case danger
}

struct AlertPopup<Content>: TopPopup where Content : View {
    var title: String
    var style: AlertType
    @ViewBuilder
    var content: () -> Content

    func createContent() -> some View {
        HStack(alignment: .top, spacing: 16) {
            Image(systemName: styleName(for: style))
                .resizable()
                .scaledToFill()
                .frame(width: 50, height: 50)

            VStack(alignment: .leading, spacing: 16) {
                Text(title)
                    .font(.title3)
                    .lineLimit(1)
                    .fontWeight(.black)

                content()
            }

            Spacer()

            Button(action: dismiss) {
                Image(systemName: "multiply.square.fill")
            }
        }
        .frame(maxWidth: .infinity)
        .ignoresSafeArea(.all)
        .foregroundColor(Color("Active Text"))
        .padding(.horizontal, 8)
        .padding(.vertical)
        .background {
            ZStack(alignment: .top) {
                Rectangle()
                    .fill(Color("Primary Background"))
            }
        }
    }
}

private extension AlertPopup {
    func styleName(for style: AlertType) -> String {
        var styleName: String = ""

        switch style {
        case .success:
            styleName = "info.circle.fill"
        case .warning:
            styleName = "exclamationmark.triangle.fill"
        case .danger:
            styleName = "exclamationmark.circle.fill"
        }

        return styleName
    }
}

struct AlertPopup_Previews: PreviewProvider {
    static var previews: some View {
        AlertPopup(title: "Something bad happened", style: .warning) {
            Text("This is the alert that never ends. Yes, it goes on and on my friend. Someone started typing it, not knowing what it was. And they'll continue typing it forever just because...")
        }
    }
}

I added .implementPopupView() to my ContentView in my WindowGroup scene. And I call the popup as follows:

        .onChange(of: errors) { _ in
            if !errors.isEmpty {
                showError(present: !errors.isEmpty, for: errors.map {
                    $0.message
                }.joined(separator: "\n"))

                errors.removeAll()
            }
        }

The errors is an array of Error objects. And showErrors looks like:

    func showError(present: Bool, for message: String) -> Void {
        AlertPopup(title: "Unable to Login", style: .danger) {
            Text(message)
        }
        .showAndStack()
    }

Apologies if my code is clunky and weird; I'm new to all of this. I appreciate your help.

FulcrumOne commented 1 year ago

No problem @9ae8sdf76, your code looks quite nice btw 🙂

Regarding the problem, it is very easy to fix. There are two places in the code that are responsible for this behaviour.

This line slightly disturbs the animation. All you have to do is just to delete it from your code: CleanShot 2023-06-01 at 17 22 46

And the second place is here: CleanShot 2023-06-01 at 17 24 03

To make it work as expected, you must replace your background declaration with this: .background(Color("Primary Background"))

And that's it, the popup you declared should work perfectly. Feel free to write if you have any further questions and have a good day 🙂

d42ohpaz commented 1 year ago

@FulcrumOne Thanks for the quick replies! I did make your suggested changes, but I'm still having the issue. After looking through the code, wouldn't the PopupConfig's backgroundColour being .white be the cause of my issue? If I manually set it to .clear it fixes the issue (I'm merely suggesting .clear be the default instead of .white).

FulcrumOne commented 1 year ago

@9ae8sdf76, hmm, weird, because it works in my case. Try another solution then - remove that background modifier completely from your code, and try to call this method (above your createContent() function)

func configurePopup(popup: TopPopupConfig) -> TopPopupConfig {
     popup.backgroundColour(Color("Primary Background"))
}

Our library gives developers a number of configuration options that can be used to configure any popup

d42ohpaz commented 1 year ago

It works as expected when I use the configurePopup() and define the backgroundColour() myself.