I'd like to have an item in the macOS menubar that takes the whole height of the bar. This can be seen, for example, in FaceTime's UI:
In my attempts, I can only get the item to extend to 1pt away from the y edges of the menu bar:
(Note that in a menubar with a notch, even FaceTime won't extend to the edges, but it still extends 1pt further on the top
and bottom
than my versions).
I've tried both the NSStatusItem
button
and (deprecate) view
to get things to work. I've also tried SwiftUI's MenuBarExtra
Simple example that leads to the second screenshot above:
final class StatusItemManager: ObservableObject {
var statusButtonItem: NSStatusItem?
var statusViewItem: NSStatusItem?
/// Note that this uses deprecated APIs -- I'd prefer to stay away from these if possible
func showViewStatusItem() {
statusViewItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
guard let statusViewItem else { return }
let iconView = NSHostingView(rootView: ItemView(title: "View"))
statusViewItem.view = iconView
statusViewItem.view?.frame = NSRect(x: 0, y: 0, width: 50, height: 40)
}
/// Non-deprecated, but still not working
func showButtonStatusItem() {
statusButtonItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
guard let statusButtonItem else { return }
let iconView = NSHostingView(rootView: ItemView(title: "Button"))
iconView.frame = NSRect(x: 0, y: 0, width: 50, height: 24)
statusButtonItem.button?.addSubview(iconView)
statusButtonItem.button?.action = #selector(menuBarButtonPressed)
statusButtonItem.button?.target = self
statusButtonItem.button?.frame = iconView.frame
}
struct ItemView: View {
var title: String
var body: some View {
Text(title)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(Color.green)
}
}
@objc func menuBarButtonPressed(_ sender: Any?) {
print("pressed")
}
}
struct ContentView: View {
@StateObject var manager = StatusItemManager()
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundColor(.accentColor)
Text("Hello, world!")
}
.padding()
.onAppear {
manager.showButtonStatusItem()
manager.showViewStatusItem()
}
}
}