swiftship/internal/skills/data/always-watchos/navigation/SKILL.md
watchOS navigation: NavigationStack, vertical page TabView, sheets, alerts — no NavigationSplitView. Use when working on shared watchOS patterns related to navigation.
npx skillsauth add abdullah4ai/apple-dev-docs navigationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
| Pattern | When to Use |
|---------|-------------|
| NavigationStack | Hierarchical drill-down (list → detail) |
| TabView vertical page | 2-4 peer sections (swipe vertically) |
| .sheet(item:) | Quick input, secondary action |
| .alert / .confirmationDialog | Confirmation, destructive actions |
| .fullScreenCover | Immersive single-purpose experience |
NavigationStack {
List(items) { item in
NavigationLink(value: item) {
ItemRow(item: item)
}
}
.navigationDestination(for: Item.self) { item in
ItemDetailView(item: item)
}
.navigationTitle("Items")
}
watchOS uses vertical paging (swipe up/down), not horizontal tabs:
TabView {
SummaryView()
DetailView()
SettingsView()
}
.tabViewStyle(.verticalPage)
For page indicators:
TabView {
Page1()
Page2()
Page3()
}
.tabViewStyle(.verticalPage(transitionStyle: .blur))
// Item-driven (preferred for existing items)
@State private var editingItem: Item?
.sheet(item: $editingItem) { item in
EditItemView(item: item)
}
// Boolean-driven (for creation)
@State private var showAdd = false
.sheet(isPresented: $showAdd) {
AddItemView()
}
Sheets on watchOS are full-screen — they slide up from the bottom.
.alert("Delete?", isPresented: $showAlert) {
Button("Delete", role: .destructive) { deleteItem() }
Button("Cancel", role: .cancel) { }
} message: {
Text("This cannot be undone.")
}
.confirmationDialog("Options", isPresented: $showDialog) {
Button("Edit") { edit() }
Button("Delete", role: .destructive) { delete() }
Button("Cancel", role: .cancel) { }
}
enum Route: Hashable {
case detail(Item)
case settings
}
NavigationStack {
List {
NavigationLink("Settings", value: Route.settings)
}
.navigationDestination(for: Route.self) { route in
switch route {
case .detail(let item):
ItemDetailView(item: item)
case .settings:
SettingsView()
}
}
}
NavigationSplitView — watch is single-column onlyTabView tabs — use .tabViewStyle(.verticalPage)Tab("Label", systemImage:) API — use plain views inside TabView.popover — use .sheet or .alert instead.presentationDetents — sheets are always full-screen on watchNavigationStack for hierarchical flows — never NavigationSplitView.tabViewStyle(.verticalPage) for peer sections — never horizontal tabsList as the root of NavigationStack for consistent watch styling.navigationTitle for context — watch shows it as a small headertesting
Use for 3D games: racing, 3D sports, board games, marble maze, tower defense, bowling. SceneKit + SceneView architecture, 3D scene hierarchy, physics, game loop, primitives, materials, cameras, particles, audio.
documentation
Game UI patterns: SwiftUI HUD overlays on SpriteKit, menus (main/pause/game-over), virtual joystick/d-pad, score displays, health bars, tutorial onboarding.
tools
Download free game sprites/textures/3D models and generate procedural assets. Covers nw_download_asset tool, texture factories, sprite atlas organization, 3D model loading, and programmatic asset creation.
testing
Use for 2D games: arcade, puzzle, sports, ping pong, platformer, shooter, 2D racing. SpriteKit + SpriteView architecture, scene hierarchy, physics, game loop, audio, particles, game feel.