Loading...

How to change the window level to floating, popUpMenu, etc. in SwiftUI?

question swiftui swift
Ram Patra Published on February 19, 2025

When developing macOS applications with SwiftUI, you might need to create floating windows that stay on top of other windows. While modern macOS versions (15+) make this straightforward with the .windowLevel(.floating) modifier, supporting older versions requires a different approach. In this post, I’ll show you how to create floating windows that work across different macOS versions.

The Modern Approach (macOS 15+)

For the latest macOS versions, setting a window level is as simple as adding a modifier:

.windowLevel(.floating)

However, this won’t work on older versions of macOS. Let’s look at a more compatible solution.

The Cross-Version Solution

To support older macOS versions, we need to access the underlying NSWindow and set its level manually. Here’s how to do it:

First, create a bridge to access the NSWindow:

import AppKit
import SwiftUI

struct WindowAccessor: NSViewRepresentable {
    var callback: (NSWindow?) -> Void
    
    func makeNSView(context: Context) -> NSView {
        let view = NSView()
        DispatchQueue.main.async {
            self.callback(view.window)
        }
        return view
    }
    
    func updateNSView(_ nsView: NSView, context: Context) {
        // No update needed
    }
}

Then, use this accessor in your SwiftUI view:

struct ContentView: View {
    var body: some View {
        VStack {
            Text("This window will float!")
                .padding()
        }
        .background(
            WindowAccessor { window in
                if let window = window {
                    window.level = NSWindow.Level.popUpMenu
                }
            }
            .frame(width: 0, height: 0)
        )
    }
}

How It Works

  1. The WindowAccessor creates an NSView that can access its parent window
  2. We use DispatchQueue.main.async to ensure the window is available when we try to access it
  3. The callback provides us with the NSWindow instance
  4. We set the window’s level to .popUpMenu to make it float above regular windows
  5. The zero-sized frame ensures our accessor view doesn’t affect the layout

Window Level Options

You can use different window levels depending on your needs:

// Common window levels
window.level = NSWindow.Level.normal        // Regular window
window.level = NSWindow.Level.floating      // Floating window
window.level = NSWindow.Level.popUpMenu     // Menu level
window.level = NSWindow.Level.modalPanel    // Modal dialog level
window.level = NSWindow.Level.screenSaver   // Screen saver level

Complete Example

Here’s a complete example of a floating window with some content:

import SwiftUI
import AppKit

struct FloatingWindowView: View {
    var body: some View {
        VStack(spacing: 20) {
            Text("Floating Window")
                .font(.title)
            
            Text("This window will stay on top of other windows")
                .multilineTextAlignment(.center)
            
            Button("Close") {
                NSApplication.shared.keyWindow?.close()
            }
        }
        .frame(width: 300, height: 200)
        .padding()
        .background(
            WindowAccessor { window in
                if let window = window {
                    window.level = NSWindow.Level.floating
                    window.title = "Floating Window"
                }
            }
            .frame(width: 0, height: 0)
        )
    }
}

Best Practices

  1. Choose the appropriate window level for your use case
  2. Consider user experience - floating windows can be intrusive
  3. Provide a way to close or minimize the floating window
  4. Test on different macOS versions to ensure compatibility

This approach gives you a reliable way to create floating windows (windows that always stay on top of other windows) that work across different macOS versions while maintaining a clean SwiftUI-style implementation.

Remember that floating windows should be used judiciously - they can be disruptive to the user’s workflow if overused. Consider whether your use case really requires a window to float above others before implementing this feature.

Presentify

Take your presentation to the next level.

FaceScreen

Put your face and name on your screen.

ToDoBar

Your to-dos on your menu bar.

Ram Patra Published on February 19, 2025
Image placeholder

Keep reading

If this article was helpful, others might be too

question swiftui macos October 15, 2023 How to display the app version and build number in a macOS/iOS SwiftUI app?

To display both the app version and build number in a SwiftUI macOS/iOS app, you can use the Bundle class to access information from the app’s Info.plist file. The Info.plist file contains various details about your application, including its version and build number. Here’s how you can do it:

question swiftui macOS January 26, 2024 How to hide the title bar in a SwiftUI macOS app?

Let’s say you have a view named ContentView and your main App file looks like this:

Like my work?

Please, feel free to reach out. I would be more than happy to chat.