Sidebar layout on macOS in SwiftUI

A common UI layout on macOS has a sidebar and detail view side by side. The sidebar contains a list of items, where the selected item is displayed on the right and displays details of it. One would expect that creating such a view hierarchy in SwiftUI should be pretty easy to set up. In this post, we’ll take a look at how to create a basic view with sidebar which supports selection.

Building the layout

We’ll build a simple sample app which shows a list of fruits in the sidebar and when clicking on any of the fruits, the right pane displays the name of the fruit. Therefore, we’ll need a struct representing a fruit, a view model for storing the list of fruits, and a property for storing the selected fruit in the sidebar.

struct Fruit: Identifiable {
let id = UUID().uuidString
let name: String
}
final class ViewModel: ObservableObject {
init(fruits: [Fruit] = ViewModel.defaultFruits) {
self.fruits = fruits
self.selectedId = fruits[1].id
}
@Published var fruits: [Fruit]
@Published var selectedId: String?
static let defaultFruits: [Fruit] = ["Apple", "Orange", "Pear"].map({ Fruit(name: $0) })
}
view raw ContentView.swift hosted with ❤ by GitHub

We can create the layout with NavigationView and NavigationLink. Inside the NavigationView we’ll first add a List where each of the item in the list is represented by a NavigationLink. One of the NavigationLink initializers takes a title, tag, and selection binding. Tag is used for identifying items in the list and setting one of the tag values to the selection binding will make the sidebar to select the item programmatically. Also, we’ll need to set the list style to “sidebar” which adds the appropriate styling to it. Finally, we’ll add a Text element, which acts as a placeholder view when there is no selection. And that is all what we need to do to get going with a view with sidebar and detail pane.

struct ContentView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
NavigationView {
List {
ForEach(viewModel.fruits) { item in
NavigationLink(item.name, tag: item.id, selection: $viewModel.selectedId) {
Text(item.name)
.navigationTitle(item.name)
}
}
}
.listStyle(.sidebar)
Text("No selection")
}
}
}
view raw ContentView.swift hosted with ❤ by GitHub
A sample app with sidebar on the left showing 3 items and detail view on the right displaying the name of the selected item.
The final sample app with a sidebar.

Summary

We used NavigationView and NavigationLink to create a common layout for macOS apps, which features a sidebar with list of items and detailed view on the right. With only a bit of code, we were able to set it up.

If this was helpful, please let me know on Twitter @toomasvahter. Feel free to subscribe to RSS feed. Thank you for reading.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s