I was trying to implement this yesterday and finally kind of found a solution, maybe not perfect, but it works.
The basic idea is that you need to create a new borderless window and then close it after it is been displayed. This is the code I use, hope it helps you.
Button("Show HUD") {
// create a borderless panel
let window = NSPanel(contentRect: NSRect(x: 0, y: 0, width: 500, height: 500), styleMask: [.fullSizeContentView, .borderless, .hudWindow], backing: .buffered, defer: false)
window.center()
// make transparent background
window.backgroundColor = .clear
let rect = NSScreen.main!.frame
// move the window to bottom center
let frame = NSRect(origin: window.frame.offsetBy(dx: 125, dy: -rect.height / 4).origin, size: window.frame.size)
window.setFrame(frame, display: true)
// create hosting view
window.contentView = NSHostingView(rootView: HUDView())
// show the window
window.makeKeyAndOrderFront(nil)
// Auto close the window after 1.8s
DispatchQueue.main.asyncAfter(deadline: .now() + 1.8) {
window.close()
}
}
And then define your HUDView
struct HUDView: View {
@State var showHUD: Bool = false
var body: some View {
ZStack {
VStack {}
.background(.clear)
.frame(width: 200, height: 200)
.onAppear {
withAnimation(.easeInOut(duration: 0.3)) {
showHUD = true
}
}
if showHUD {
VStack(spacing: 20) {
Image(systemName: "doc.on.clipboard.fill").font(.system(size: 72))
Text("Code Copied").font(.system(size: 20))
}
.frame(width: 200, height: 200)
// the background could be .regularMaterial, but for some reason it can not works, so instead I created my own BlurView...
.background(BlurView())
.cornerRadius(20)
.foregroundColor(.white.opacity(0.8))
.overlay(RoundedRectangle(cornerRadius: 20).strokeBorder(.white.opacity(0.15), lineWidth: 1))
}
}
}
}
BlurView defines
struct BlurView: NSViewRepresentable {
func makeNSView(context: Context) -> NSVisualEffectView {
let blurView = NSVisualEffectView()
blurView.blendingMode = .behindWindow
blurView.isEmphasized = true
blurView.material = .hudWindow
blurView.autoresizingMask = [.width, .height]
blurView.state = NSVisualEffectView.State.active
return blurView
}
func updateNSView(_ nsView: NSVisualEffectView, context: Context) {
}
}
The preview should show something like below, pretty cool , isn't it?
