Is there a way to Show Hide a sidebar with a button?

.commands{
  SidebarCommands()
}

If I add the above to a MacOS app, the program gains a Show Sidebar / Hide Sidebar menu option on the View menu. I'd like to add a button to show or hide the sidebar such as the one in Xcode, but I can't find a way to do it? I would have thought that there would be a simple framework call, but my internet searches haven't turned up anything.

I also like the way that Xcode places the Hide Sidebar button on the sidebar, but when the sidebar is hidden, the Show Sidebar button is on the left side of the window. Has any one figured out how to do this with SwiftUI?

Accepted Reply

@MarkErbaugh Sorry for the late reply. Yes, you are correct that there is no native SwiftUI way to accomplish the task. As for a sidebar on the right side, there is a way to accomplish this but it is more complicated. I don't have any code right now that accomplishes it, but in the past I did something similar using a horizontal split view. It would appear and disappear depending on an @State var showRightSidebar = "false" and then I had a button that would toggle that variable to show and hid the view just like you would with a modal or sheet view.

  • Thanks for the reply. I did manage to get a right side sidebar sort of working using a Split View. but I was unable to get it to animate opening and closing. Even with a .withAnimation on the toggle of the @State var, the view just popped in and out. Also, if the user resized the right side view once it was hidden and re-shown, it reverted to it's original width. It really seems to me that SwiftUI is designed for iOS apps and support for the things needed by MacOS apps was an afterthought.

Add a Comment

Replies

Hey, You can add the button to the toolbar window using the following code after a list. The toolbar item placement is set to ".automatic", which is what causes the button to appear in the sidebar toolbar like in Xcode.

.toolbar {
			ToolbarItem(placement: .automatic) {
				Button(action: toggleSidebar, label: {
					Image(systemName: "sidebar.leading")
				})
			}

Then you need to add "toggleSidebar" function, which is:

	   #if os(iOS)
	   #else
		NSApp.sendAction(#selector(NSSplitViewController.toggleSidebar(_:)), to: nil, from: nil)
	   #endif
	}
}

All together you get something like this:

	var body: some View {
		List {
			NavigationLink(destination: ...) 
			NavigationLink(destination: ...) 
			NavigationLink(destination: ...) 
		}.listStyle(SidebarListStyle())
		.toolbar {
			ToolbarItem(placement: .automatic) {
				Button(action: toggleSidebar, label: {
					Image(systemName: "sidebar.leading")
				})
			}
		}.navigationTitle("Search")
	}
	private func toggleSidebar() {
	   #if os(iOS)
	   #else
		NSApp.sendAction(#selector(NSSplitViewController.toggleSidebar(_:)), to: nil, from: nil)
	   #endif

	}

}

Don't mind the empty NavigationLinks in the list, they are just for example. The contents of the list do not really matter as long as the list works Hope this helps

  • Thanks, the NSSplitViewController was what was missing. I notice from the help documentation (and the NS in the name) that this is part of AppKit. Am I correct in assuming that there is no native SwiftUI to accomplish this? Also, is there a similar way to show and hide a sidebar on the right side of the main window (i.e. an inspector panel)?

Add a Comment

@MarkErbaugh Sorry for the late reply. Yes, you are correct that there is no native SwiftUI way to accomplish the task. As for a sidebar on the right side, there is a way to accomplish this but it is more complicated. I don't have any code right now that accomplishes it, but in the past I did something similar using a horizontal split view. It would appear and disappear depending on an @State var showRightSidebar = "false" and then I had a button that would toggle that variable to show and hid the view just like you would with a modal or sheet view.

  • Thanks for the reply. I did manage to get a right side sidebar sort of working using a Split View. but I was unable to get it to animate opening and closing. Even with a .withAnimation on the toggle of the @State var, the view just popped in and out. Also, if the user resized the right side view once it was hidden and re-shown, it reverted to it's original width. It really seems to me that SwiftUI is designed for iOS apps and support for the things needed by MacOS apps was an afterthought.

Add a Comment