All checks were successful
Gitea Actions Demo / publish (push) Successful in 47s
168 lines
5.0 KiB
Markdown
168 lines
5.0 KiB
Markdown
+++
|
|
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).
|
|
|
|
<div class="pattern-images">
|
|
{{ image(url="sidebarGNOME.png", alt="A navigation view with a sidebar on GNOME" transparent=true) }}
|
|
|
|
{{ image(url="sidebarWindows.png", alt="A navigation view with a sidebar on Windows") }}
|
|
</div>
|
|
|
|
## Top Bar Design
|
|
|
|
The top bar design will be used for five items or less if the sidebar design is not forced.
|
|
|
|
<div class="pattern-images">
|
|
{{ image(url="topGNOME.png", alt="A navigation view with a top bar on GNOME" transparent=true) }}
|
|
|
|
{{ image(url="topWindows.png", alt="A navigation view with a top bar on GNOME") }}
|
|
</div>
|
|
|
|
## 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.
|
|
|
|
```swift
|
|
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).
|
|
|
|
```swift
|
|
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(_:)`](https://aparoksha.aparoksha.dev/documentation/aparoksha/flatnavigation/forcesplitview(_:)) modifier.
|
|
|
|
```swift
|
|
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.
|
|
|
|
<div class="pattern-images">
|
|
{{ image(url="primaryGNOME.png", alt="A navigation view with a sidebar and a primary action on GNOME" transparent=true) }}
|
|
|
|
{{ 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") }}
|
|
</div>
|
|
|
|
```swift
|
|
FlatNavigation(items, selection: $selectedItem) {
|
|
// The content.
|
|
Text(selectedItem.description)
|
|
}
|
|
.primaryAction(Loc.addItem, icon: .plus) {
|
|
// The action.
|
|
items.append(.init(title: Loc.newItem))
|
|
}
|
|
```
|
|
|
|
## Guidelines
|
|
|
|
- <a class="external" href="https://developer.gnome.org/hig/guidelines/navigation.html#flat-navigation">GNOME</a>
|
|
- <a class="external" href="https://learn.microsoft.com/en-us/windows/apps/design/basics/navigation-basics">Windows</a>
|
|
|
|
## Documentation
|
|
|
|
- <a class="external" href="https://aparoksha.aparoksha.dev/documentation/aparoksha/flatnavigation">Reference Documentation</a>
|
|
- <a class="external" href="https://adwaita-swift.aparoksha.dev/documentation/adwaita/navigationsplitview">Native GNOME Implementation (Sidebar)</a>
|
|
- <a class="external" href="https://adwaita-swift.aparoksha.dev/documentation/adwaita/viewswitcher">Native GNOME Implementation (Top Bar)</a>
|
|
- <a class="external" href="https://winui-swift.aparoksha.dev/documentation/winui_swift/navigationview">Native Windows Implementation</a>
|