malik
malik

Reputation: 1

Opening a Sheet inside a MenuBarExtra

I'm trying to open a Sheet inside a MenuBarExtra in SwiftUI. I don't know why it happens, but clicking inside the Sheet dismisses the MenuBarExtra and is therefore essentially unusable.

I made this minimal example to showcase the problem:

import SwiftUI

struct ContentView: View {
@State var sheetDisplayed: Bool = true
    var body: some View {
        Text("test")
            .padding()
            .frame(minWidth: 500, minHeight: 500)
            .sheet(isPresented: $sheetDisplayed) {
                VStack {
                    Text("test2")
                    Button("click me") {}
                }
                .frame(minWidth: 200, minHeight: 200)
            }
    }
}

@main
struct MenuBarTestApp: App {
    var body: some Scene {
            MenuBarExtra {
                ContentView()
            } label: {
                Image(systemName: "circle")
            }.menuBarExtraStyle(.window)
    }
}

Clicking either on the "click me" button or anywhere inside the Sheet will dismiss the menu bar app. I have confirmed this happens on both macOS 14.6 and 15.

Upvotes: 0

Views: 125

Answers (1)

soundflix
soundflix

Reputation: 2793

I tested on macOS 13.6.8, Xcode 15.2 with your example code in a fresh project:

  • Clicking the circle icon shows the popover window with the sheet centered inside.
  • I can click anywhere inside the window or sheet and nothing changes, as I would expect from the code.

So the behavior you are seeing might actually be a framework bug in the versions you tried.


I have extended your code to test dismissing the sheet. I found that using the enviroment's dismiss method actually dismisses the menu bar window, without setting false to the binding sheetDisplayed (not expected), whereas setting the binding directly dismisses the sheet and not the window (expected).

While this is not a solution, it might clarify a part of your issue.

Here is my tester app:

import SwiftUI

struct ContentView: View {
    @State private var sheetDisplayed: Bool = false
    @Environment(\.dismiss) private var dismiss
    
    var body: some View {
        Text("Menu Bar Window")
            .padding()
        Button("Present Sheet") {
            sheetDisplayed = true
        }
        .padding()
        .frame(minWidth: 500, minHeight: 500)
        .sheet(isPresented: $sheetDisplayed) {
            VStack {
                Text("Sheet")
                Button("Falsify") {
                    sheetDisplayed = false  // <- This works as expected!
                }
                Button("Dismiss") {
                    dismiss() // <- `dismiss` will close the menu bar window.
                }
            }
            .frame(minWidth: 200, minHeight: 200)
            
        }
        .task(id: sheetDisplayed) {
            print("sheetDisplayed: \(sheetDisplayed)") // will not print false with `dismiss`!
        }
    }
}

UPDATE:

I found out that my observation is actually an expected behavior. I put my ContentView in a Window scene instead of MenuBarExtra and dismiss also closes the window. Putting the sheet content in a separate view struct makes dismiss work on the sheet.

Upvotes: 0

Related Questions