home / skills / rshankras / claude-code-apple-skills / navigation-patterns

navigation-patterns skill

/skills/ios/navigation-patterns

This skill helps you design and fix SwiftUI navigation architectures using NavigationStack, NavigationSplitView, and programmatic paths to improve app flow.

npx playbooks add skill rshankras/claude-code-apple-skills --skill navigation-patterns

Review the files below or copy the command above to add this skill to your agents.

Files (6)
SKILL.md
5.0 KB
---
name: navigation-patterns
description: SwiftUI navigation architecture patterns including NavigationStack, NavigationSplitView, TabView, programmatic navigation, and custom transitions. Use when reviewing or building navigation, fixing navigation bugs, or architecting app flow.
allowed-tools: [Read, Glob, Grep]
---

# Navigation Patterns

Comprehensive guide for SwiftUI navigation architecture on iOS, iPadOS, and macOS. Covers the modern navigation APIs (iOS 16+/macOS 13+) with patterns for common and advanced use cases.

## When This Skill Activates

- User is building or reviewing navigation architecture
- User has navigation-related bugs (stack not updating, back button issues, state loss)
- User asks about NavigationStack, NavigationSplitView, TabView, or NavigationPath
- User needs programmatic navigation (push, pop, pop-to-root)
- User is implementing deep linking that connects to navigation
- User asks about navigation transitions or animations
- User is choosing between navigation approaches for their app

## Decision Tree

Use this to pick the right navigation container:

```
What is the app structure?
│
├─ Flat sections (3-5 top-level areas)
│  └─ TabView → see tab-view.md
│
├─ Hierarchical drill-down (list → detail)
│  └─ NavigationStack → see navigation-stack.md
│
├─ Sidebar + content (macOS / iPad)
│  ├─ Two columns → NavigationSplitView → see navigation-split-view.md
│  └─ Three columns → NavigationSplitView → see navigation-split-view.md
│
└─ Combined (tabs with drill-down, sidebar with stacks)
   └─ TabView + NavigationStack per tab
      OR NavigationSplitView + NavigationStack in detail
```

## Quick Reference

| Pattern | Container | Min OS | Reference |
|---------|-----------|--------|-----------|
| Simple drill-down | `NavigationStack` | iOS 16 | `navigation-stack.md` |
| Value-based links | `NavigationLink(value:)` | iOS 16 | `navigation-stack.md` |
| Programmatic push/pop | `NavigationPath` | iOS 16 | `programmatic-navigation.md` |
| Pop to root | `path = NavigationPath()` | iOS 16 | `programmatic-navigation.md` |
| State restoration | `NavigationPath.CodableRepresentation` | iOS 16 | `programmatic-navigation.md` |
| Two-column layout | `NavigationSplitView` | iOS 16 | `navigation-split-view.md` |
| Three-column layout | `NavigationSplitView` | iOS 16 | `navigation-split-view.md` |
| Column visibility | `NavigationSplitViewVisibility` | iOS 16 | `navigation-split-view.md` |
| Tab bar | `TabView` | iOS 13 | `tab-view.md` |
| Customizable tabs | `Tab` + `TabView` | iOS 18 | `tab-view.md` |
| Sidebar tabs (iPad) | `.tabViewStyle(.sidebarAdaptable)` | iOS 18 | `tab-view.md` |
| Zoom transition | `.navigationTransition(.zoom)` | iOS 18 | `navigation-transitions.md` |
| Custom transitions | `NavigationTransition` | iOS 18 | `navigation-transitions.md` |

## Process

### 1. Identify Navigation Needs

Read the user's code or requirements to determine:
- App structure (flat, hierarchical, sidebar-based)
- Target platforms (iOS only, iPad adaptive, macOS)
- Whether programmatic navigation is needed
- Deep linking requirements

### 2. Load Relevant Reference Files

Based on the need, read from this directory:
- `navigation-stack.md` — NavigationStack, NavigationLink, navigationDestination
- `navigation-split-view.md` — Two/three column layouts, column control, adaptive behavior
- `tab-view.md` — TabView, iOS 18 customizable tabs, sidebar mode
- `programmatic-navigation.md` — NavigationPath, state restoration, coordinators, pop-to-root
- `navigation-transitions.md` — Custom push/pop transitions (iOS 18+)

### 3. Review or Recommend

Apply patterns from the reference files. Check for common mistakes:

- [ ] Using deprecated `NavigationView` instead of `NavigationStack`/`NavigationSplitView`
- [ ] Using `NavigationLink(destination:)` instead of `NavigationLink(value:)` + `.navigationDestination`
- [ ] Placing `NavigationStack` inside `NavigationSplitView` detail (usually wrong)
- [ ] Missing `.navigationDestination` registration for a value type
- [ ] NavigationPath not `@State` or not in the right scope
- [ ] Multiple NavigationStacks competing for the same navigation context
- [ ] Hard-coding navigation instead of using `NavigationPath` for programmatic control
- [ ] Not handling deep links through the navigation system

### 4. Cross-Reference

- For **deep linking URL handling**, see `generators/deep-linking/` skill
- For **navigation animations**, see `design/animation-patterns/transitions.md`
- For **macOS sidebar patterns**, see `macos/ui-review-tahoe/swiftui-macos.md`

## References

- [NavigationStack](https://developer.apple.com/documentation/swiftui/navigationstack)
- [NavigationSplitView](https://developer.apple.com/documentation/swiftui/navigationsplitview)
- [NavigationPath](https://developer.apple.com/documentation/swiftui/navigationpath)
- [TabView](https://developer.apple.com/documentation/swiftui/tabview)
- [Migrating to new navigation types](https://developer.apple.com/documentation/swiftui/migrating-to-new-navigation-types)

Overview

This skill documents SwiftUI navigation architecture patterns for iOS, iPadOS, and macOS. It focuses on modern APIs like NavigationStack, NavigationSplitView, TabView, NavigationPath, and custom transitions to help design reliable, testable app flows.

How this skill works

It inspects app structure and navigation code to recommend the appropriate container (stack, split, or tab) and usage patterns. It checks for common issues—incorrect container placement, missing navigationDestination registrations, improper NavigationPath scope, and migration from deprecated APIs—and proposes concrete fixes and alternatives.

When to use it

  • Design or review app navigation architecture (flat, hierarchical, sidebar).
  • Fix navigation bugs such as broken back buttons, state loss, or stack not updating.
  • Implement programmatic navigation: push, pop, pop-to-root, or deep linking integration.
  • Choose between NavigationStack, NavigationSplitView, and TabView for target platforms.
  • Add or troubleshoot custom navigation transitions and animations.

Best practices

  • Prefer NavigationStack / NavigationSplitView over deprecated NavigationView for modern OS targets.
  • Use NavigationLink(value:) with navigationDestination registrations for type-safe routing.
  • Keep NavigationPath as @State or in a shared view model scoped to the navigation owner for programmatic control and state restoration.
  • Avoid nesting competing NavigationStacks that can split navigation context; place stacks at the correct container level.
  • Persist NavigationPath.CodableRepresentation for state restoration and deep-link mapping when required.

Example use cases

  • Single-column drill-down list → detail: use NavigationStack with value-based links.
  • Tabbed app with independent stacks: TabView with a NavigationStack per tab and separate NavigationPath state.
  • iPad / macOS master-detail: NavigationSplitView with stacks in the detail column for drill-down behavior.
  • Programmatic flows: push/pop/pop-to-root driven by NavigationPath in a coordinator or view model.
  • Deep linking: decode URL to values, restore NavigationPath.CodableRepresentation and set path to navigate to target screen.

FAQ

When should I use NavigationSplitView vs NavigationStack?

Use NavigationSplitView for sidebar or multi-column layouts on iPad/macOS; use NavigationStack for single-column hierarchical drill-downs. Combine them when a split layout needs drill-down in the detail column.

How do I restore navigation state after app restart or deep link?

Serialize the NavigationPath using NavigationPath.CodableRepresentation (or your own codable model) and restore it on launch. Map incoming deep-link URLs to the same value types used by navigationDestination and set the path accordingly.