SwiftUI Toolbar Features

Quick Reference

FeatureModifier/TypePurpose
.toolbar(id:)Customizable toolbarUser can add/remove/reorder
ToolbarSpacerSpacing controlFixed or flexible spacing
.searchToolbarBehavior()Search field displayMinimize/expand behavior
DefaultToolbarItemSystem itemsReposition system controls
.matchedTransitionSource()TransitionsZoom from toolbar items

Customizable Toolbars

Basic Setup

.toolbar(id: "main") {
    ToolbarItem(id: "save") { SaveButton() }
    ToolbarItem(id: "share") { ShareButton() }
    ToolbarSpacer(.flexible)
    ToolbarItem(id: "more") { MoreButton() }
}

Spacer Types

ToolbarSpacer(.fixed)     // Fixed width
ToolbarSpacer(.flexible)  // Pushes items apart

Search Integration

Minimize Behavior

@State private var searchText = ""

NavigationStack {
    ContentView()
        .searchable($searchText)
        .searchToolbarBehavior(.minimize)  // Compact search button
}
.toolbar {
    ToolbarItem(placement: .bottomBar) { Button1() }
    DefaultToolbarItem(kind: .search, placement: .bottomBar)
    ToolbarItem(placement: .bottomBar) { Button2() }
}

Placement Options

Common Placements

.toolbar {
    // Navigation bar
    ToolbarItem(placement: .navigationBarLeading) { }
    ToolbarItem(placement: .navigationBarTrailing) { }
    ToolbarItem(placement: .principal) { }
    
    // Bottom bar (iOS)
    ToolbarItem(placement: .bottomBar) { }
    
    // Large title area
    ToolbarItem(placement: .largeSubtitle) { CustomSubtitle() }
}

Large Subtitle

NavigationStack {
    Content()
        .navigationTitle("Title")
        .navigationSubtitle("Subtitle")
        .toolbar {
            ToolbarItem(placement: .largeSubtitle) {
                // Overrides navigationSubtitle
                CustomSubtitleView()
            }
        }
}

Visual Effects

Matched Transitions

@State private var showDetail = false
@Namespace private var namespace

NavigationStack {
    Content()
        .toolbar {
            ToolbarItem {
                Button("Open") { showDetail = true }
                    .matchedTransitionSource(id: "btn", in: namespace)
            }
        }
        .sheet(isPresented: $showDetail) {
            DetailView()
                .navigationTransition(.zoom(sourceID: "btn", in: namespace))
        }
}

Background Visibility

.toolbar(id: "main") {
    ToolbarItem(id: "status", placement: .principal) {
        StatusView()
            .sharedBackgroundVisibility(.hidden)  // No glass background
    }
}

System Items

Default Items

.toolbar {
    // Reposition system search
    DefaultToolbarItem(kind: .search, placement: .bottomBar)
    
    // Sidebar toggle
    DefaultToolbarItem(kind: .sidebar, placement: .navigationBarLeading)
}

Platform Considerations

iOS/iPadOS

#if os(iOS)
.toolbar {
    ToolbarItemGroup(placement: .bottomBar) {
        // Bottom bar items for iPhone
    }
}
#endif

macOS

#if os(macOS)
.toolbar {
    ToolbarItem(placement: .automatic) {
        // macOS toolbar items
    }
}
#endif

Common Patterns

Dynamic Toolbar

@State private var isEditing = false

.toolbar {
    if isEditing {
        ToolbarItem(id: "done") { DoneButton() }
    } else {
        ToolbarItem(id: "edit") { EditButton() }
    }
}

Grouped Actions

.toolbar {
    ToolbarItemGroup(placement: .bottomBar) {
        Button("One") { }
        Button("Two") { }
        Button("Three") { }
    }
}

Contextual Items

@State private var selection: Item?

.toolbar {
    if selection != nil {
        ToolbarItem { DeleteButton() }
        ToolbarItem { ShareButton() }
    }
}

Best Practices

  1. Unique IDs: Use meaningful identifiers for customizable items
  2. Logical Groups: Use spacers to group related actions
  3. Platform Awareness: Test on all target platforms
  4. Consistent Placement: Follow platform conventions
  5. Minimal Items: Avoid overcrowding toolbars

Troubleshooting

IssueSolution
Items not customizableAdd id to toolbar and items
Search not minimizingApply .searchToolbarBehavior(.minimize)
Transition not workingCheck namespace and ID match
Items hiddenCheck placement compatibility

References