swiftship/internal/skills/data/always-watchos/components/SKILL.md
watchOS UI components: watch-sized buttons, grouped lists, toggles, pickers, progress, empty states. Use when working on shared watchOS patterns related to components.
npx skillsauth add abdullah4ai/apple-developer-toolkit componentsInstall 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.
BUTTON HIERARCHY (watch-sized):
| Level | Style | Use Case |
|-------|-------|----------|
| Primary | .borderedProminent | Main action (Start, Save) |
| Secondary | .bordered | Alternative (Cancel, Edit) |
| Destructive | .borderedProminent + .tint(.red) | Delete, Remove |
.frame(maxWidth: .infinity) needed.controlSize(.mini) or .controlSize(.small) for compact button groups.borderedProminent per screenButton() — never .onTapGesture for actions// Primary action
Button("Start") { start() }
.buttonStyle(.borderedProminent)
// Compact button pair
HStack {
Button("Skip") { skip() }
.buttonStyle(.bordered)
.controlSize(.small)
Button("Next") { next() }
.buttonStyle(.borderedProminent)
.controlSize(.small)
}
LIST PATTERNS:
// Grouped list (primary pattern for watchOS)
List {
Section("Today") {
ForEach(todayItems) { item in
NavigationLink(value: item) {
HStack {
Image(systemName: item.icon)
Text(item.title)
Spacer()
Text(item.value)
.foregroundStyle(.secondary)
}
}
}
}
Section("Settings") {
Toggle("Notifications", isOn: $notifications)
}
}
TOGGLE:
// Toggle in a list section
Section("Preferences") {
Toggle("Sound", isOn: $soundEnabled)
Toggle("Haptics", isOn: $hapticsEnabled)
}
PICKER:
// Wheel picker (good for watch)
Picker("Speed", selection: $speed) {
Text("Slow").tag(Speed.slow)
Text("Medium").tag(Speed.medium)
Text("Fast").tag(Speed.fast)
}
// Navigation link picker for many options
Picker("Category", selection: $category) {
ForEach(categories) { cat in
Text(cat.name).tag(cat)
}
}
PROGRESS:
// Circular progress (fits watch aesthetic)
ProgressView(value: progress, total: 1.0)
.progressViewStyle(.circular)
// Linear progress
ProgressView(value: 0.6)
// Indeterminate
ProgressView("Loading...")
GAUGE (watch-native):
Gauge(value: heartRate, in: 40...200) {
Text("BPM")
} currentValueLabel: {
Text("\(Int(heartRate))")
} minimumValueLabel: {
Text("40")
} maximumValueLabel: {
Text("200")
}
.gaugeStyle(.accessoryCircular)
EMPTY STATES:
ContentUnavailableView(
"No Workouts",
systemImage: "figure.run",
description: Text("Start a workout to see it here")
)
DATE/TIME DISPLAY:
// Use system date formatting
Text(Date.now, style: .time)
.font(AppTheme.Fonts.title2)
Text(Date.now, style: .relative)
.font(AppTheme.Fonts.caption)
NOT AVAILABLE ON watchOS:
.textFieldStyle(.roundedBorder) — watch text input is system-driven.redacted(reason: .placeholder) skeleton loading (too complex for watch).controlSize(.large) buttons — watch buttons fill width by default.popover presentationsRULES:
List with sections as the primary content container.font(.title3) for icons in liststesting
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.