swiftship/internal/skills/data/always-tvos/components/SKILL.md
tvOS UI components: card buttons, focus states, media tiles, text entry, progress indicators. Use when working on tvOS component patterns, focus styling, or card-based UI. Triggers: Button, card, focus, CardButtonStyle, component, tile.
npx skillsauth add abdullah4ai/apple-dev-docs 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.
tvOS defaults to dark appearance. Design for a 10-foot viewing distance on large screens.
Color rules for tvOS:
.background / .secondarySystemBackground) when possible"Show, don't tell":
CARD BUTTON (primary tvOS pattern):
Button {
select(item)
} label: {
VStack(alignment: .leading, spacing: AppTheme.Spacing.sm) {
Image(item.thumbnail)
.resizable()
.aspectRatio(16/9, contentMode: .fill)
.frame(width: 300, height: 170)
.clipped()
.clipShape(.rect(cornerRadius: AppTheme.Style.cornerRadius))
Text(item.title)
.font(AppTheme.Fonts.callout)
.lineLimit(2)
}
}
.buttonStyle(.card)
PLAIN BUTTON:
Button("Play", systemImage: "play.fill") {
play()
}
.buttonStyle(.borderedProminent)
BUTTON HIERARCHY:
| Level | Style | Use Case |
|-------|-------|----------|
| Primary card | .buttonStyle(.card) | Media tiles, browsable items |
| Primary action | .borderedProminent | Play, Subscribe, Buy |
| Secondary | .bordered | More Info, Add to List |
| Destructive | .borderedProminent + .tint(.red) | Delete, Remove |
tvOS highlights focused elements with a lift/shadow effect. Focus is the primary interaction model:
struct FocusableCard: View {
@Environment(\.isFocused) var isFocused
var body: some View {
VStack {
Image(item.image)
.resizable()
.aspectRatio(16/9, contentMode: .fill)
Text(item.title)
.font(AppTheme.Fonts.callout)
}
.scaleEffect(isFocused ? 1.05 : 1.0)
.animation(.easeInOut(duration: 0.2), value: isFocused)
}
}
For custom focus effects:
.focusable()
.onFocusChange { focused in
withAnimation(.easeInOut(duration: 0.15)) {
isFocused = focused
}
}
tvOS requires generous spacing since users sit far from the screen:
| Element | Recommended | |---------|-------------| | Between sections | 60pt | | Between cards | 40pt | | Horizontal content padding | 80pt | | Minimum focusable element | 150x100pt |
tvOS uses a system keyboard — text input is limited:
@State private var searchText = ""
TextField("Search", text: $searchText)
.textFieldStyle(.plain)
Prefer selection over free-text input:
Picker("Category", selection: $category) {
ForEach(categories) { cat in
Text(cat.name).tag(cat)
}
}
// Indeterminate
ProgressView("Loading...")
// Overlay loading
ZStack {
ContentView()
if isLoading {
ProgressView()
.scaleEffect(1.5)
}
}
List {
Section("Settings") {
NavigationLink("Account") {
AccountView()
}
Toggle("Notifications", isOn: $notifications)
Picker("Quality", selection: $quality) {
Text("Auto").tag(Quality.auto)
Text("High").tag(Quality.high)
Text("Low").tag(Quality.low)
}
}
}
ContentUnavailableView(
"No Results",
systemImage: "magnifyingglass",
description: Text("Try a different search term")
)
.textFieldStyle(.roundedBorder) — tvOS text fields are plain.contextMenu — use focused button actions.popover.buttonStyle(.card) for browsable media content.borderedProminent per visible screen area@Environment(\.isFocused) for custom focus effectstesting
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.