axiom-swiftui-nav-ref

1
1
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-swiftui-nav-diag

CharlesWiltgen

Use when debugging navigation not responding, unexpected pops, deep links showing wrong screen, state lost on tab switch or background, crashes in navigationDestination, or any SwiftUI navigation failure - systematic diagnostics with production crisis defense

54

axiom-swiftui-26-ref

CharlesWiltgen

Use when implementing iOS 26 SwiftUI features - covers Liquid Glass design system, performance improvements, @Animatable macro, 3D spatial layout, scene bridging, WebView/WebPage, AttributedString rich text editing, drag and drop enhancements, and visionOS integration for iOS 26+

33

axiom-extensions-widgets-ref

CharlesWiltgen

Use when implementing widgets, Live Activities, Control Center controls, or app extensions - comprehensive API reference for WidgetKit, ActivityKit, App Groups, and extension lifecycle for iOS 14+

13

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.

253

axiom-camera-capture-ref

CharlesWiltgen

Reference — AVCaptureSession, AVCapturePhotoSettings, AVCapturePhotoOutput, RotationCoordinator, photoQualityPrioritization, deferred processing, AVCaptureMovieFileOutput, session presets, capture device APIs

42

axiom-swiftdata

CharlesWiltgen

Use when working with SwiftData - @Model definitions, @Query in SwiftUI, @Relationship macros, ModelContext patterns, CloudKit integration, iOS 26+ features, and Swift 6 concurrency with @MainActor — Apple's native persistence framework

12

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.

1,6851,428

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."

1,2631,324

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.

1,5331,147

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.

1,355809

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.

1,263727

pdf-to-markdown

aliceisjustplaying

Convert entire PDF documents to clean, structured Markdown for full context loading. Use this skill when the user wants to extract ALL text from a PDF into context (not grep/search), when discussing or analyzing PDF content in full, when the user mentions "load the whole PDF", "bring the PDF into context", "read the entire PDF", or when partial extraction/grepping would miss important context. This is the preferred method for PDF text extraction over page-by-page or grep approaches.

1,481684