axiom-swiftui-nav-ref

0
0
Source

Reference — Comprehensive SwiftUI navigation guide covering NavigationStack (iOS 16+), NavigationSplitView (iOS 16+), NavigationPath, deep linking, state restoration, Tab+Navigation integration (iOS 18+), Liquid Glass navigation (iOS 26+), and coordinator patterns

Install

mkdir -p .claude/skills/axiom-swiftui-nav-ref && curl -L -o skill.zip "https://mcp.directory/api/skills/download/5003" && unzip -o skill.zip -d .claude/skills/axiom-swiftui-nav-ref && rm skill.zip

Installs to .claude/skills/axiom-swiftui-nav-ref

About this skill

SwiftUI Navigation API Reference

Overview

SwiftUI's navigation APIs provide data-driven, programmatic navigation that scales from simple stacks to complex multi-column layouts. Introduced in iOS 16 (2022) with NavigationStack and NavigationSplitView, evolved in iOS 18 (2024) with Tab/Sidebar unification, and refined in iOS 26 (2025) with Liquid Glass design.

Evolution timeline

  • 2022 (iOS 16) NavigationStack, NavigationSplitView, NavigationPath, value-based NavigationLink
  • 2024 (iOS 18) Tab/Sidebar unification, sidebarAdaptable style, zoom navigation transition
  • 2025 (iOS 26) Liquid Glass navigation chrome, bottom-aligned search, floating tab bars, backgroundExtensionEffect

Key capabilities

  • Data-driven navigation NavigationPath represents stack state, enabling programmatic push/pop and deep linking
  • Multi-column layouts NavigationSplitView adapts automatically (3-column on iPad → single stack on iPhone)
  • State restoration Codable NavigationPath + SceneStorage for persistence across app launches
  • Tab integration Per-tab NavigationStack with state preservation on tab switch (iOS 18+)
  • Liquid Glass Automatic glass navigation bars, sidebars, and toolbars (iOS 26+)

When to use vs UIKit

  • SwiftUI navigation New apps, multiplatform, simpler navigation flows → Use NavigationStack/SplitView
  • UINavigationController Complex coordinator patterns, legacy code, specific UIKit features → Consider UIKit

Related Skills

  • Use axiom-swiftui-nav for anti-patterns, decision trees, pressure scenarios
  • Use axiom-swiftui-nav-diag for systematic troubleshooting of navigation issues

When to Use This Skill

Use this skill when:

  • Implementing navigation APIs NavigationStack, NavigationSplitView, NavigationPath, Tab+Navigation
  • Deep linking or state restoration URL routing, Codable NavigationPath, SceneStorage
  • Adopting iOS 26+ features Liquid Glass navigation, bottom-aligned search, tab bar minimization
  • Choosing navigation architecture Stack vs SplitView vs coordinator patterns

API Evolution

Timeline

YeariOS VersionKey Features
2020iOS 14NavigationView (deprecated iOS 16)
2022iOS 16NavigationStack, NavigationSplitView, NavigationPath, value-based NavigationLink
2024iOS 18Tab/Sidebar unification, sidebarAdaptable, TabSection, zoom transitions
2025iOS 26Liquid Glass navigation, backgroundExtensionEffect, tabBarMinimizeBehavior

NavigationView (Deprecated)

NavigationView is deprecated as of iOS 16. Use NavigationStack (single-column push/pop) or NavigationSplitView (multi-column) exclusively in new code. Key improvements: single NavigationPath replaces per-link isActive bindings, value-based type safety, built-in Codable state restoration. See "Migrating to new navigation types" documentation.


NavigationStack Complete Reference

NavigationStack represents a push-pop interface like Settings on iPhone or System Settings on macOS.

1.1 Creating NavigationStack

Basic NavigationStack

NavigationStack {
    List(Category.allCases) { category in
        NavigationLink(category.name, value: category)
    }
    .navigationTitle("Categories")
    .navigationDestination(for: Category.self) { category in
        CategoryDetail(category: category)
    }
}

With Path Binding (WWDC 2022, 6:05)

struct PushableStack: View {
    @State private var path: [Recipe] = []
    @StateObject private var dataModel = DataModel()

    var body: some View {
        NavigationStack(path: $path) {
            List(Category.allCases) { category in
                Section(category.localizedName) {
                    ForEach(dataModel.recipes(in: category)) { recipe in
                        NavigationLink(recipe.name, value: recipe)
                    }
                }
            }
            .navigationTitle("Categories")
            .navigationDestination(for: Recipe.self) { recipe in
                RecipeDetail(recipe: recipe)
            }
        }
        .environmentObject(dataModel)
    }
}

Path binding + value-presenting NavigationLink + navigationDestination(for:) form the core data-driven navigation pattern.

1.2 NavigationLink (Value-Based)

Value-presenting NavigationLink

// Correct: Value-based (iOS 16+)
NavigationLink(recipe.name, value: recipe)

// Correct: With custom label
NavigationLink(value: recipe) {
    RecipeTile(recipe: recipe)
}

// Deprecated: View-based (iOS 13-15)
NavigationLink(recipe.name) {
    RecipeDetail(recipe: recipe)  // Don't use in new code
}

How NavigationLink works with NavigationStack

  1. NavigationStack maintains a path collection
  2. Tapping a value-presenting link appends the value to the path
  3. NavigationStack maps navigationDestination modifiers over path values
  4. Views are pushed onto the stack based on destination mappings

1.3 navigationDestination Modifier

Single Type

.navigationDestination(for: Recipe.self) { recipe in
    RecipeDetail(recipe: recipe)
}

Multiple Types

NavigationStack(path: $path) {
    RootView()
        .navigationDestination(for: Recipe.self) { recipe in
            RecipeDetail(recipe: recipe)
        }
        .navigationDestination(for: Category.self) { category in
            CategoryList(category: category)
        }
        .navigationDestination(for: Chef.self) { chef in
            ChefProfile(chef: chef)
        }
}

Navigation Anti-Patterns

  • Never mix navigationDestination(for:) and NavigationLink(destination:) in the same NavigationStack hierarchy — causes undefined behavior
  • Register navigationDestination(for:) once per data type — duplicates cause the wrong view to appear

Placement rules

  • Place navigationDestination outside lazy containers (not inside ForEach)
  • Place near related NavigationLinks for code organization
  • Must be inside NavigationStack hierarchy
// Correct: Outside lazy container
ScrollView {
    LazyVGrid(columns: columns) {
        ForEach(recipes) { recipe in
            NavigationLink(value: recipe) {
                RecipeTile(recipe: recipe)
            }
        }
    }
}
.navigationDestination(for: Recipe.self) { recipe in
    RecipeDetail(recipe: recipe)
}

// Wrong: Inside ForEach (may not be loaded)
ForEach(recipes) { recipe in
    NavigationLink(value: recipe) { RecipeTile(recipe: recipe) }
        .navigationDestination(for: Recipe.self) { r in  // Don't do this
            RecipeDetail(recipe: r)
        }
}

1.4 NavigationPath

NavigationPath is a type-erased collection for heterogeneous navigation stacks.

Typed Array vs NavigationPath

// Typed array: All values same type
@State private var path: [Recipe] = []

// NavigationPath: Mixed types
@State private var path = NavigationPath()

NavigationPath Operations

// Append value
path.append(recipe)

// Pop to previous
path.removeLast()

// Pop to root
path.removeLast(path.count)
// or
path = NavigationPath()

// Check count
if path.count > 0 { ... }

// Deep link: Set multiple values
path.append(category)
path.append(recipe)

Codable Support

// NavigationPath is Codable when all values are Codable
@State private var path = NavigationPath()

// Encode
let data = try JSONEncoder().encode(path.codable)

// Decode
let codableRep = try JSONDecoder().decode(NavigationPath.CodableRepresentation.self, from: data)
path = NavigationPath(codableRep)

NavigationSplitView Complete Reference

NavigationSplitView creates multi-column layouts that adapt to device size.

2.1 Two-Column Layout

Basic Two-Column (WWDC 2022, 10:40)

struct MultipleColumns: View {
    @State private var selectedCategory: Category?
    @State private var selectedRecipe: Recipe?
    @StateObject private var dataModel = DataModel()

    var body: some View {
        NavigationSplitView {
            List(Category.allCases, selection: $selectedCategory) { category in
                NavigationLink(category.localizedName, value: category)
            }
            .navigationTitle("Categories")
        } detail: {
            if let recipe = selectedRecipe {
                RecipeDetail(recipe: recipe)
            } else {
                Text("Select a recipe")
            }
        }
    }
}

2.2 Three-Column Layout

Add a content: closure between sidebar and detail for a middle column:

NavigationSplitView {
    List(Category.allCases, selection: $selectedCategory) { category in
        NavigationLink(category.localizedName, value: category)
    }
} content: {
    List(dataModel.recipes(in: selectedCategory), selection: $selectedRecipe) { recipe in
        NavigationLink(recipe.name, value: recipe)
    }
} detail: {
    RecipeDetail(recipe: selectedRecipe)
}

2.3 NavigationSplitView with NavigationStack

Place a NavigationStack(path:) inside the detail column for grid-to-detail drill-down while preserving sidebar selection:

NavigationSplitView {
    List(Category.allCases, selection: $selectedCategory) { ... }
} detail: {
    NavigationStack(path: $path) {
        RecipeGrid(category: selectedCategory)
            .navigationDestination(for: Recipe.self) { recipe in
                RecipeDetail(recipe: recipe)
            }
    }
}

2.4 Column Visibility

@State private var columnVisibility: NavigationSplitViewVisibility = .all

NavigationSplitView(columnVisibility: $columnVisibility) {
    Sidebar()
} content: {
    Content()
} detail: {
    Detail()
}

// Programmatically control visibility
columnVisibility = .detailOnly  // Hide sidebar and content
columnVisibility = .all          // Show all columns
columnVisibility = .automatic    // System decides

2.5 Automatic Adaptation

NavigationSplitView a


Content truncated.

axiom-ios-build

CharlesWiltgen

Use when ANY iOS build fails, test crashes, Xcode misbehaves, or environment issue occurs before debugging code. Covers build failures, compilation errors, dependency conflicts, simulator problems, environment-first diagnostics.

91

axiom-getting-started

CharlesWiltgen

Use when first installing Axiom, unsure which skill to use, want an overview of available skills, or need help finding the right skill for your situation — interactive onboarding that recommends skills based on your project and current focus

00

axiom-ui-testing

CharlesWiltgen

Use when writing UI tests, recording interactions, tests have race conditions, timing dependencies, inconsistent pass/fail behavior, or XCTest UI tests are flaky - covers Recording UI Automation (WWDC 2025), condition-based waiting, network conditioning, multi-factor testing, crash debugging, and accessibility-first testing patterns

00

axiom-core-spotlight-ref

CharlesWiltgen

Use when indexing app content for Spotlight search, using NSUserActivity for prediction/handoff, or choosing between CSSearchableItem and IndexedEntity - covers Core Spotlight framework and NSUserActivity integration for iOS 9+

00

axiom-vision-diag

CharlesWiltgen

subject not detected, hand pose missing landmarks, low confidence observations, Vision performance, coordinate conversion, VisionKit errors, observation nil, text not recognized, barcode not detected, DataScannerViewController not working, document scan issues

00

axiom-now-playing-carplay

CharlesWiltgen

CarPlay Now Playing integration patterns. Use when implementing CarPlay audio controls, CPNowPlayingTemplate customization, or debugging CarPlay-specific issues.

00

You might also like

flutter-development

aj-geddes

Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.

643969

drawio-diagrams-enhanced

jgtolentino

Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.

591705

ui-ux-pro-max

nextlevelbuilder

"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."

318398

godot

bfollington

This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.

339397

nano-banana-pro

garg-aayush

Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.

451339

fastapi-templates

wshobson

Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.

304231

Stay ahead of the MCP ecosystem

Get weekly updates on new skills and servers.