cocoaswiftuinswindowappkitnstoolbar

How to put SwiftUI button into NSToolbar?


This is how SwiftUI can be inserted into NSToolbar using an accessory view controller:

import SwiftUI
import PlaygroundSupport

var hostingView = NSHostingView(rootView:
  ZStack {
    Color.clear
    HStack {
      Text("Hey")
      Text("SwiftUI")
    }
  }
  .padding()
  .edgesIgnoringSafeArea(.all)
)
hostingView.frame.size = hostingView.fittingSize

let titlebarAccessory = NSTitlebarAccessoryViewController()
titlebarAccessory.view = hostingView
titlebarAccessory.layoutAttribute = .trailing

let mask: NSWindow.StyleMask = [.titled, .closable, .miniaturizable, .resizable]
let window = NSWindow(
  contentRect: .init(x: 0, y: 0, width: 480, height: 300),
  styleMask: mask, backing: .buffered, defer: false)
window.center()
window.contentView = NSHostingView(rootView: Color(.windowBackgroundColor))
window.toolbar = .init()
window.titleVisibility = .hidden
window.addTitlebarAccessoryViewController(titlebarAccessory)

PlaygroundPage.current.liveView = window.contentView?.superview

The code above does work:

If we insert a button however:

HStack {
  Text("Hey")
  Button(action: {}) {
    Text("SwiftUI")
  }
}

It would not work as expected:

Any suggestions?

P. S. This is a working solution:

HStack {
  Text("Hey")
    .offset(x: 0, y: -1)
  Button(action: {}) {
    Text("SwiftUI")
      .offset(x: 0, y: -7)
  }
}
.font(.caption)


Solution

  • 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.