swiftship/internal/skills/data/ui/design-system/SKILL.md
Design system: tokens, themes, consistent spacing, color, typography. Use when implementing UI patterns related to design systems.
npx skillsauth add abdullah4ai/apple-developer-toolkit design-systemInstall 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.
Every app MUST use a centralized theme with nested enums for Colors, Fonts, and Spacing. Do NOT use a flat enum with top-level static properties.
// REQUIRED — always use nested enums
import SwiftUI
enum AppTheme {
enum Colors {
static let accent = Color.blue // one accent per app
static let textPrimary = Color.primary
static let textSecondary = Color.secondary
static let background = Color(.systemBackground)
static let surface = Color(.secondarySystemBackground)
static let cardBackground = Color(.secondarySystemGroupedBackground)
}
enum Fonts {
static let largeTitle = Font.largeTitle
static let title = Font.title
static let headline = Font.headline
static let body = Font.body
static let caption = Font.caption
}
enum Spacing {
static let small: CGFloat = 8
static let medium: CGFloat = 16
static let large: CGFloat = 24
static let cornerRadius: CGFloat = 12
}
}
// FORBIDDEN — never use flat structure
enum AppTheme {
static let accentColor = Color.blue // ❌ wrong
static let spacing: CGFloat = 8 // ❌ wrong
}
Reference as: AppTheme.Colors.accent, AppTheme.Fonts.headline, AppTheme.Spacing.medium
.largeTitle, .title, .headline, .body, .captionAppTheme.Fonts for consistent sizingImage(systemName: "symbol.name").symbolRenderingMode(.hierarchical) or .symbolRenderingMode(.palette) for visual depth.primary, .secondary, Color(.systemBackground)AppTheme.Spacing constants throughoutEvery list or collection MUST have an empty state. Use ContentUnavailableView (iOS 17+) for a polished look:
// Required — show when collection is empty
if items.isEmpty {
ContentUnavailableView(
"No Notes Yet",
systemImage: "note.text",
description: Text("Tap + to create your first note")
)
} else {
// Show the list
}
For custom empty states, use a styled VStack with SF Symbol + descriptive text:
VStack(spacing: 16) {
Image(systemName: "tray")
.font(.system(size: 48))
.foregroundStyle(.secondary)
Text("Nothing here yet")
.font(.title3)
Text("Add your first item to get started")
.font(.subheadline)
.foregroundStyle(.secondary)
}
Use subtle, purposeful animations for state changes and list mutations:
// Toggle/complete actions — spring animation
withAnimation(.spring) {
item.isComplete.toggle()
}
// List insertions/removals — combine opacity + scale
.transition(.opacity.combined(with: .scale))
// Numeric text changes
.contentTransition(.numericText())
// Filter/tab changes
.animation(.default, value: selectedFilter)
Rules:
withAnimation(.spring) for toggle/complete state changes.transition(.opacity.combined(with: .scale)) for list add/remove.spring and .default curves onlytesting
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.