agentsclimarketplace

Ios navigation

Skill ajwadrana/skills/ios-design/skills/ios-navigation

Provide reusable skills, agents, and commands for Claude Code to improve workflow and iOS UX design with clear structure and integration.

Install
npx -y skills add ajwadrana/skills --skill ios-navigation

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

iOS navigation guidance. Triggers on: navigation, tab bar, NavigationStack, sheets, modals, app structure, routing, TabView, NavigationSplitView, deep linking.

SKILL.md

7.1 KB, as published. Nobody here has run it

iOS Navigation — App Structure, Routing & Adaptive Layout


1. Navigation Patterns

Choose the right container for each context:

PatternWhen to Use
NavigationStackPush/pop within a section. Most common.
TabViewTop-level app sections (3–5 tabs). Glass tab bar in iOS 26.
.sheet(item:)Focused task or detail. Preferred over isPresented: — drives from data.
.fullScreenCoverImmersive flows (onboarding, media playback, composition).
NavigationSplitViewMulti-column layout for iPad/macOS. Sidebar + detail.
.inspectorSecondary detail panel — supplementary info without leaving context.
.popoverQuick info or actions on iPad. Falls back to sheet on iPhone.

Decision Guide

  • "Where am I in the app?" → TabView
  • "Go deeper into content" → NavigationStack push
  • "Do a focused task, then come back" → Sheet
  • "Show two things side by side" → NavigationSplitView
  • "Quick action on this item" → Context menu or popover

2. iOS 26 Glass Navigation

iOS 26 automatically applies glass materials to system navigation elements:

Glass Tab Bar

TabView {
    Tab("Home", systemImage: "house") {
        HomeView()
    }
    Tab("Search", systemImage: "magnifyingglass") {
        SearchView()
    }
    Tab("Profile", systemImage: "person") {
        ProfileView()
    }
}

The tab bar gets glass treatment automatically. Don't fight it with custom tab bars.

Glass Navigation Bar

NavigationStack {
    ContentView()
        .navigationTitle("Feed")
        .toolbarBackgroundVisibility(.automatic) // Let glass show
}

Scroll Extension Under Sidebar

NavigationSplitView {
    SidebarView()
} detail: {
    DetailView()
        .scrollExtensionMode(.underSidebar) // Content extends under glass sidebar
}

3. App Scaffolding Pattern

Standard wiring for a multi-tab app with navigation and sheets:

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct ContentView: View {
    var body: some View {
        TabView {
            Tab("Home", systemImage: "house") {
                HomeNavigationStack()
            }
            Tab("Search", systemImage: "magnifyingglass") {
                SearchNavigationStack()
            }
            Tab("Profile", systemImage: "person") {
                ProfileNavigationStack()
            }
        }
    }
}

Per-Tab Navigation Stack

struct HomeNavigationStack: View {
    @State private var path = NavigationPath()
    @State private var presentedSheet: SheetDestination?

    var body: some View {
        NavigationStack(path: $path) {
            HomeView(path: $path, presentedSheet: $presentedSheet)
                .navigationDestination(for: Post.self) { post in
                    PostDetailView(post: post)
                }
                .navigationDestination(for: User.self) { user in
                    UserProfileView(user: user)
                }
        }
        .sheet(item: $presentedSheet) { destination in
            destination.view
        }
    }
}

Sheet Routing Enum

enum SheetDestination: Identifiable {
    case compose
    case settings
    case editProfile(User)

    var id: String {
        switch self {
        case .compose: "compose"
        case .settings: "settings"
        case .editProfile(let user): "editProfile-\(user.id)"
        }
    }

    @ViewBuilder
    var view: some View {
        switch self {
        case .compose:
            ComposeView()
        case .settings:
            SettingsView()
        case .editProfile(let user):
            EditProfileView(user: user)
        }
    }
}

4. Sheet Best Practices

  • Use item: over isPresented: — sheets driven by data are easier to reason about
  • Sheets own their dismissal — call @Environment(\.dismiss) inside the sheet, not a callback
  • Don't pass closures for actions — the sheet should perform its own save/cancel logic
  • Size sheets appropriately:
    .sheet(item: $item) { item in
        DetailView(item: item)
            .presentationDetents([.medium, .large])
            .presentationDragIndicator(.visible)
    }
    
  • Sheets get their own NavigationStack if they need a toolbar:
    NavigationStack {
        ComposeView()
            .toolbar {
                ToolbarItem(.cancellationAction) { Button("Cancel") { dismiss() } }
                ToolbarItem(.confirmationAction) { Button("Save") { save(); dismiss() } }
            }
    }
    

5. Adaptive Layout

Size Classes

@Environment(\.horizontalSizeClass) private var horizontalSizeClass

var body: some View {
    if horizontalSizeClass == .regular {
        // iPad / landscape — two-column layout
        NavigationSplitView {
            SidebarView()
        } detail: {
            DetailView()
        }
    } else {
        // iPhone — single column
        NavigationStack {
            ListView()
        }
    }
}

ViewThatFits

// Automatically picks the first child that fits
ViewThatFits {
    HStack { /* wide layout */ }
    VStack { /* narrow layout */ }
}

iPad Considerations

  • Use NavigationSplitView for primary/detail patterns
  • Support multiple windows with @Environment(\.supportsMultipleWindows)
  • Pointer/keyboard: add .hoverEffect(), support keyboard shortcuts
  • Don't assume full-screen — iPad runs apps in split view

6. Deep Linking

URL Routing

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onOpenURL { url in
                    handleDeepLink(url)
                }
        }
    }

    func handleDeepLink(_ url: URL) {
        // Parse URL components and navigate
        guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
              let host = components.host else { return }

        switch host {
        case "post":
            if let id = components.queryItems?.first(where: { $0.name == "id" })?.value {
                // Navigate to post
            }
        case "profile":
            // Navigate to profile tab
        default:
            break
        }
    }
}

Programmatic Navigation with NavigationPath

@State private var path = NavigationPath()

// Push programmatically
path.append(somePost)       // Pushes PostDetailView
path.append(someUser)       // Pushes UserProfileView

// Pop to root
path = NavigationPath()

// Pop one level
path.removeLast()

Use NavigationPath for type-erased heterogeneous paths. Use [SomeType] for homogeneous paths (simpler, Codable by default).

State Restoration

// Save navigation state
@SceneStorage("navigationPath") private var pathData: Data?

// Encode/decode NavigationPath for persistence
// NavigationPath supports Codable when all pushed types are Codable

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.