MenuBarExtra
.NSStatusItem
NSWindow
(when using the .window
style)MenuBarExtra
menu
and window
based styles (see Known Issues)There is no 1st-party MenuBarExtra API to obtain or set the menu presentation state, access the status item, or access the popup's NSWindow. (As of Xcode 14.3 / SwiftUI 4)
.menuBarExtraAccess(isPresented:) { statusItem in }
scene modifier with
NSStatusItem
if needed.introspectMenuBarExtraWindow { window in }
view modifier passing in the NSWindow
referenceThe library is available as a Swift Package Manager (SPM) package.
Use the URL https://github.com/orchetect/MenuBarExtraAccess
when adding the library to a project or Swift package.
Then import the library:
import SwiftUI
import MenuBarExtraAccess
An example of showing the menu extra menu by clicking a button in a window:
@main struct MyApp: App {
@State var isMenuPresented: Bool = false
var body: some Scene {
WindowGroup {
Button("Show Menu") { isMenuPresented = true }
}
MenuBarExtra("MyApp Menu", systemImage: "folder") {
Button("Menu Item 1") { print("Menu Item 1") }
Button("Menu Item 2") { print("Menu Item 2") }
}
.menuBarExtraStyle(.menu)
.menuBarExtraAccess(isPresented: $isMenuPresented) { statusItem in // <-- the magic ✨
// access status item or store it in a @State var
}
}
}
An example of a button in the popup window dismissing the popup and performing an action:
@main struct MyApp: App {
@State var isMenuPresented: Bool = false
var body: some Scene {
MenuBarExtra("MyApp Menu", systemImage: "folder") {
MyMenu(isMenuPresented: $isMenuPresented)
.introspectMenuBarExtraWindow { window in // <-- the magic ✨
window.animationBehavior = .alertPanel
}
}
.menuBarExtraStyle(.window)
.menuBarExtraAccess(isPresented: $isMenuPresented) { statusItem in // <-- the magic ✨
// access status item or store it in a @State var
}
}
}
struct MyMenu: View {
@Binding var isMenuPresented: Bool
var body: some View {
Button("Perform Action") {
isMenuPresented = false
performSomeAction()
}
}
}
MenuBarExtraAccess is fully compatible with one or multiple MenuBarExtra in an app.
Just add an index number parameter to .menuBarExtraAccess()
and .introspectMenuBarExtraWindow()
that reflects the order of MenuBarExtra
declarations.
var body: some Scene {
MenuBarExtra("MyApp Menu A", systemImage: "folder") {
MyMenu(isMenuPresented: $isMenuPresented)
.introspectMenuBarExtraWindow(index: 0) { window in // <-- add index 0
// ...
}
}
.menuBarExtraStyle(.window)
.menuBarExtraAccess(index: 0, isPresented: $isMenuPresented) // <-- add index 0
MenuBarExtra("MyApp Menu B", systemImage: "folder") {
MyMenu(isMenuPresented: $isMenuPresented)
.introspectMenuBarExtraWindow(index: 1) { window in // <-- add index 1
// ...
}
}
.menuBarExtraStyle(.window)
.menuBarExtraAccess(index: 1, isPresented: $isMenuPresented) // <-- add index 1
}
The hope is that Apple implements native versions of these features (and more) in future iterations of SwiftUI!
Until then, a radar has been filed as a feature request: FB11984872
Check out MacControlCenterUI, a SwiftUI package built on MenuBarExtraAccess for easily building Control Center style menus.
.menuBarExtraStyle(.menu)
, the popup menu blocks the runloop so setting the isPresented
binding to false
while the menu is presented has no effect. The user must dismiss the menu themself to allow event flow to continue. We have no control over this until Apple decides to change the MenuBarExtra behavior.MenuBarExtra
works. This is being investigated and a workaround may be possible for a future release.Coded by a bunch of 🐹 hamsters in a trenchcoat that calls itself @orchetect.
Licensed under the MIT license. See LICENSE for details.
If you enjoy using MenuBarExtraAccess and want to contribute to open-source financially, GitHub sponsorship is much appreciated. Feedback and code contributions are also welcome.
Contributions are welcome. Posting in Discussions first prior to new submitting PRs for features or modifications is encouraged.
link |
Stars: 26 |
Last commit: 1 week ago |
NSStatusItem
access in menuBarExtraAccess()
Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics