5.0 KiB
+++ title = "Flat Navigation" description = "A navigation pattern for views of equal importance." date = 2024-11-16 [taxonomies] tags = ["Aparoksha", "Windows", "Linux", "macOS"] +++
In a flat navigation structure, each page is equivalent in importance and can be opened form any of the others. Different platforms offer different solutions for flat navigation, such as a top bar or a sidebar. This view will select the most appropriate based on number of elements and available space.
Label views with capitalized nouns with a similar length. Order the elements according to what is most useful for the user. The icons should clearly communicate a page's function even without the label.
Note that this view should be used exclusively as a direct child of a window.
Sidebar Design
The sidebar design will be used if there are more than five items or the developer chooses to force the sidebar design (see below).
{{ image(url="sidebarWindows.png", alt="A navigation view with a sidebar on Windows") }}
Top Bar Design
The top bar design will be used for five items or less if the sidebar design is not forced.
{{ image(url="topWindows.png", alt="A navigation view with a top bar on GNOME") }}
Equatable Items
A flat navigation view can be initialized either with identifiable or with equatable items. The initializer for equatable items is useful for a fixed number of items.
struct ContentView: View {
@State private var selectedItem: Page = .navigation
var view: Body {
FlatNavigation(Page.allCases, selection: $selectedItem) {
// The content.
Text(selectedItem.description)
}
}
}
enum Page: FlatNavigationItem, CaseIterable {
// The pages.
case navigation
case alert
// The title of the page.
var description: String {
switch self {
case .navigation:
Loc.navigation
case .alert:
Loc.alert
}
}
// The icon of the page.
var icon: Icon {
switch self {
case .navigation:
.navigation
case .alert:
.warning
}
}
}
Identifiable Items
The initializer for identifiable items should be used for a dynamic list of items. It will automatically force the sidebar design (more information below).
struct ContentView: View {
@State private var selectedItem: UUID?
@State private var items: [Item] = [.init(title: "Item 1"), .init(title: "Item 2")]
var view: Body {
FlatNavigation(items, selection: $selectedItem) {
// The content.
Text("Content")
}
}
}
struct Item: DynamicFlatNavigationItem, Identifiable {
let id: UUID = .init()
var title: String
// The title of the page.
var description: String { title }
// The icon of the page.
var icon: Icon { .document }
}
Force the Sidebar Design
Force the sidebar design with the forceSplitView(_:)
modifier.
FlatNavigation(Page.allCases, selection: $selectedItem) {
// The content.
Text(selectedItem.description)
}
.forceSplitView()
Primary Action
The primary action usually modifies the navigation items or triggers an important action.
{{ image(url="primaryWindows.png", alt="A navigation view with a sidebar and a primary action on Windows") }}
{{ image(url="primaryGNOMETop.png", alt="A navigation view with a sidebar on GNOME" transparent=true) }}
{{ image(url="primaryWindowsTop.png", alt="A navigation view with a sidebar on Windows") }}
FlatNavigation(items, selection: $selectedItem) {
// The content.
Text(selectedItem.description)
}
.primaryAction(Loc.addItem, icon: .plus) {
// The action.
items.append(.init(title: Loc.newItem))
}