Is there a way for MenuBarExtra
to handle click on the icon and perform some action, without opening a view?
I know it's possible with NSStatusItem
, but I already have other MenuBarExtra
items that I would like to keep an order (doesn't seem like there is a way to reorder them either).
Here is a rather convoluted way to do this. Use a .window
style menu bar extra, and use a NSViewControllerRepresentable
as the window's content.
In the NSViewController
, you can override viewWillAppear
to detect the click. Then dismiss the window immediately.
struct MyView: NSViewControllerRepresentable {
@Environment(\.dismiss) var dismiss
let onClick: () -> Void
class ChangeDetector: NSViewController {
var dismiss: DismissAction?
var onClick: (() -> Void)?
override func viewWillAppear() {
super.viewWillAppear()
onClick?()
Task {
dismiss?()
}
}
override func loadView() {
self.view = NSView()
}
}
func makeNSViewController(context: Context) -> ChangeDetector {
let detector = ChangeDetector()
return detector
}
func updateNSViewController(_ nsView: ChangeDetector, context: Context) {
nsView.dismiss = dismiss
nsView.onClick = onClick
}
}
MenuBarExtra("Some title", systemImage: "circle.fill") {
MyView() {
print("Clicked!")
}
}
.menuBarExtraStyle(.window)
As for ordering NSStatusItem
s, note that the user can manually drag the status items while holding down the command key to reorder them.