swiftship/internal/skills/data/ui/layout/SKILL.md
Layout patterns: VStack, HStack, Grid, LazyVGrid, GeometryReader, alignment. Use when implementing UI patterns related to layout.
npx skillsauth add abdullah4ai/apple-dev-docs layoutInstall 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.
Comprehensive guide to stack layouts, view composition, subview extraction, and layout best practices.
// Good - relative to actual layout
GeometryReader { geometry in
VStack {
HeaderView()
.frame(height: geometry.size.height * 0.2)
ContentView()
}
}
// Avoid - magic numbers that don't adapt
VStack {
HeaderView()
.frame(height: 150) // Doesn't adapt to different screens
ContentView()
}
Custom views should own static containers but not lazy/repeatable ones.
// Good - owns static container
struct HeaderView: View {
var body: some View {
HStack {
Image(systemName: "star")
Text("Title")
Spacer()
}
}
}
// BAD - re-executes complexSection() on every tap
struct ParentView: View {
@State private var count = 0
var body: some View {
VStack {
Button("Tap: \(count)") { count += 1 }
complexSection() // Re-executes every tap!
}
}
@ViewBuilder
func complexSection() -> some View {
ForEach(0..<100) { i in
HStack {
Image(systemName: "star")
Text("Item \(i)")
}
}
}
}
// GOOD - ComplexSection body SKIPPED when its inputs don't change
struct ParentView: View {
@State private var count = 0
var body: some View {
VStack {
Button("Tap: \(count)") { count += 1 }
ComplexSection() // Body skipped during re-evaluation
}
}
}
struct ComplexSection: View {
var body: some View {
ForEach(0..<100) { i in
HStack {
Image(systemName: "star")
Text("Item \(i)")
}
}
}
}
Use ZStack to compose multiple peer views that should be layered together.
Prefer overlay / background when decorating a primary view.
// GOOD - decoration in overlay
Button("Continue") { }
.overlay(alignment: .trailing) {
Image(systemName: "lock.fill")
.padding(.trailing, 8)
}
// GOOD - background shape takes parent size
HStack(spacing: 12) {
Image(systemName: "tray")
Text("Inbox")
}
.background {
Capsule()
.strokeBorder(.blue, lineWidth: 2)
}
// Good - logic in testable model (iOS 17+)
@Observable
@MainActor
final class LoginViewModel {
var email = ""
var password = ""
var isValid: Bool {
!email.isEmpty && password.count >= 8
}
func login() async throws { }
}
struct LoginView: View {
@State private var viewModel = LoginViewModel()
var body: some View {
Form {
TextField("Email", text: $viewModel.email)
SecureField("Password", text: $viewModel.password)
Button("Login") {
Task { try? await viewModel.login() }
}
.disabled(!viewModel.isValid)
}
}
}
testing
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.