rensbreur / SwiftTUI

SwiftUI for terminal applications
MIT License
1.21k stars 44 forks source link

Modal Windows #38

Open mjKosmic opened 3 months ago

mjKosmic commented 3 months ago

Is there any way to create little modal windows? I'm thinking something like theres a setting that someone can edit and the edit happens in a popup modal window in the center of the screen. Currently it looks like attempting to overlay a center-justified view, even a relatively small one, results in the whole screen getting re-rendered and losing the presenting view entirely. I suspect this is because the entire view needs to be buffered to be able to know the dimensions for where the center is. Is there some clever method to get something like this working? Or is this possible as a feature request?

rensbreur commented 3 months ago

Hi @mjKosmic ,

Is there any way to create little modal windows? I'm thinking something like theres a setting that someone can edit and the edit happens in a popup modal window in the center of the screen.

That's on my wishlist but it's not supported right now. You could draw a pop-up over other content using a ZStack, but it won't prevent the content below from being selected.

Currently it looks like attempting to overlay a center-justified view, even a relatively small one, results in the whole screen getting re-rendered and losing the presenting view entirely.

I'm not sure I understand, how are you trying to overlay that center view?

mjKosmic commented 3 months ago

I mean just using something as simple as the following:

struct ModalView: View {
    var dismiss: () -> Void

    var body: some View {
        VStack(alignment: .center) {
            HStack(alignment: .center) {
                VStack {
                    Text("Modal")
                    Button("Dismiss") {
                        dismiss()
                    }
                }
            }
        }
    }
}

results in the entier screen getting redrawn. Interestingly, it looks like if i embed that modal code in a ZStack, it doesn't center the text and button, but rather renders it in the top left corner

here is the relevant ZStack embedding code:

ZStack {
    VStack {
        HStack {
            Spacer()
            Text("Background")
        }
        Spacer()
    }
    .border()
    ModalView() {
        //dismiss logic
    }
}
Screenshot 2024-07-01 at 10 25 10 PM Screenshot 2024-07-01 at 10 22 28 PM
rensbreur commented 3 months ago

By default, ZStack in SwiftTUI indeed uses a top leading alignment. You can use ZStack(alignment: .center) instead.

In your original code without the ZStack, I suppose you are trying to show the ModalView in the root view, could you help me and send the code of that root view as well so I can try to reproduce? By "redraws the entire screen", you mean that you cannot see the background view, right?

mjKosmic commented 3 months ago

It looks like the reason i got what appeared to be a full screen modal was because i was switching on an enum and not actually appropriately presenting the modal view. This along with a frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center) on the outer-most container view (Group in this case) in the root view placed the modal view in the center of the screen. I think that part is working as expected.

However, a modal view modifier would still be really cool :)