Triple Trouble
A minimal example of three-column navigation for iPad and macOS using SwiftUI.
See the post for more info.
WARNING: This solution requires Big Sur.
Code
import SwiftUI
@main
struct TestSidebarApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
// Uncomment to hide title
// .windowToolbarStyle(UnifiedWindowToolbarStyle(showsTitle: false))
.commands {
SidebarCommands()
}
}
}
struct ContentView: View {
var body: some View {
NavigationView {
SidebarView()
Text("No Sidebar Selection")
Text("No Message Selection")
}
}
}
struct SidebarView: View {
@State private var isDefaultItemActive = true
var body: some View {
let list = List {
Text("Favorites")
.font(.caption)
.foregroundColor(.secondary)
NavigationLink(destination: IndoxView(), isActive: $isDefaultItemActive) {
Label("Inbox", systemImage: "tray.2")
}
NavigationLink(destination: SentView()) {
Label("Sent", systemImage: "paperplane")
}
}
.listStyle(SidebarListStyle())
#if os(macOS)
list.toolbar {
Button(action: toggleSidebar) {
Image(systemName: "sidebar.left")
}
}
#else
list
#endif
}
}
#if os(macOS)
private func toggleSidebar() {
NSApp.keyWindow?.firstResponder?
.tryToPerform(#selector(NSSplitViewController.toggleSidebar(_:)), with: nil)
}
#endif
struct IndoxView: View {
var body: some View {
List(Array(0...100).map(String.init), id: \.self) { message in
NavigationLink(destination: MessageDetailsView(message: message)) {
Text(message)
}
}
.navigationTitle("Inbox")
.toolbar {
Button(action: { /* Open filters */ }) {
Image(systemName: "line.horizontal.3.decrease.circle")
}
}
}
}
struct SentView: View {
var body: some View {
Text("No Sent Messages")
.navigationTitle("Sent")
.toolbar {
Button(action: {}) {
Image(systemName: "line.horizontal.3.decrease.circle")
}
}
}
}
struct MessageDetailsView: View {
let message: String
var body: some View {
Text("Details for \(message)")
.toolbar {
Button(action: {}) {
Image(systemName: "square.and.arrow.up")
}
}
}
}