This is how SwiftUI can be inserted into NSToolbar
using an accessory view controller:
import SwiftUI
import PlaygroundSupport
var hostingView
Posting my comment as an answer per request. Not necessarily a reliable solution but as a workaround you can use
Text("SwiftUI")
.padding(EdgeInsets(top: -7, leading: 0, bottom: 0, trailing: 0))
or .offset
on the Text in the button. No guarantees on how long that will last as a solution.
The way I eventually handled it (making it work also when the user makes the window full screen AND regardless of the height* of the content) is below. Note that I'm using Toolbar view in an NSHostingView within NSTitlebarAccessoryViewController of a macOS app built with most recent Xcode version (obviously, on macOS Catalina).
Important things: *you still need to setup a fixed height for the frame (but at least you won't rely to the "variable" -7) and offset to top by half of the actual height ONLY when there is safe area top inset (in full screen mode, apparently, it isn't) and therefore GeometryReader is a must:
struct Toolbar : View {
var body: some View {
GeometryReader { geometry in
VStack {
Text("1st row")
Text("2nd row")
}
.offset(y: geometry.safeAreaInsets.top > 0 ? -geometry.size.height / 2 : 0)
}
.frame(height: 42)
}
}
and where window is created:
let toolbar = NSHostingView(rootView: Toolbar())
toolbar.frame.size = toolbar.fittingSize
let toolbarController = NSTitlebarAccessoryViewController()
toolbarController.view = toolbar
window.addTitlebarAccessoryViewController(toolbarController)
Toolbar item has more vertical space. To fix that use Spacer view it will push the button to the top:
VStack {
Button(action: {}) {
Text("Text")
}.frame(height: 22)
Spacer()
}
It seems that applying PlainButtonStyle
to the button helps.
Default style is doing some weird magic that is breaking the layout in NSToolbar.