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.

Take your presentation to the next level.

Put your face and name on your screen.

Your to-dos on your menu bar.

Fill forms using your right-click menu.

Ram Patra Published on February 19, 2025
Image placeholder

Keep reading

If this article was helpful, others might be too

question swiftui macos September 3, 2024 Two ways to open a window programmatically in SwiftUI

SwiftUI provides an openWindow environment variable on macOS that allows you to open windows programmatically. Here’s how you can use it to open a new window when a button is clicked:

question swiftui swift September 8, 2024 How to loop through an enum in SwiftUI?

In SwiftUI, looping through an enum is not directly possible without some extra work because enums in Swift don’t inherently support iteration. However, you can achieve this by making the enum CaseIterable, which automatically provides a collection of all cases in the enum.

question swiftui iOS April 2, 2024 How to force an app or a view to open in landscape only mode in iOS using SwiftUI?

In SwiftUI, you can force an app to open in landscape mode by configuring the supported interface orientations in your app’s target settings. Here’s a step-by-step guide to configuring interface orientations in Xcode:

Like my work?

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