OverviewHistoryStatsSecurity
npx skills add ...
Documentation
SKILL.md
npx skills add wshobson/agents --skill mobile-ios-design
Master iOS Human Interface Guidelines and SwiftUI patterns for building native iOS apps. Use when designing iOS interfaces, implementing SwiftUI views, or ensuring apps follow Apple's design principles.
npx skills add wshobson/agents --skill mobile-ios-design
Master iOS Human Interface Guidelines (HIG) and SwiftUI patterns to build polished, native iOS applications that feel at home on Apple platforms.
Clarity: Content is legible, icons are precise, adornments are subtle Deference: UI helps users understand content without competing with it Depth: Visual layers and motion convey hierarchy and enable navigation
Platform Considerations:
Stack-Based Layouts:
Grid Layouts:
NavigationStack (iOS 16+):
TabView (iOS 18+):
SF Symbols:
Dynamic Type:
Colors and Materials:
Shadows and Depth:
.primary, .secondary, .background for automatic light/dark mode support.body, .headline) instead of fixed sizes.accessibilityLabel() and .accessibilityHint() modifierssafeAreaInset and avoid hardcoded padding at screen edges@SceneStorage for preserving user state.fixedSize() sparingly; prefer flexible layoutsLazyVStack/LazyHStack for long scrolling listsNavigationLink values are Hashable// Adaptive grid that fills available width
LazyVGrid(columns: [
GridItem(.adaptive(minimum: 150, maximum: 200))
], spacing: 16) {
ForEach(items) { item in
ItemCard(item: item)
}
}
// Fixed column grid
LazyVGrid(columns: [
GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible())
], spacing: 12) {
ForEach(items) { item in
ItemThumbnail(item: item)
}
}struct ContentView: View {
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
List(items) { item in
NavigationLink(value: item) {
ItemRow(item: item)
}
}
.navigationTitle("Items")
.navigationDestination(for: Item.self) { item in
ItemDetailView(item: item)
}
}
}
}struct MainTabView: View {
@State private var selectedTab = 0
var body: some View {
TabView(selection: $selectedTab) {
Tab("Home", systemImage: "house", value: 0) {
HomeView()
}
Tab("Search", systemImage: "magnifyingglass", value: 1) {
SearchView()
}
Tab("Profile", systemImage: "person", value: 2) {
ProfileView()
}
}
}
}// Basic symbol
Image(systemName: "heart.fill")
.foregroundStyle(.red)
// Symbol with rendering mode
Image(systemName: "cloud.sun.fill")
.symbolRenderingMode(.multicolor)
// Variable symbol (iOS 16+)
Image(systemName: "speaker.wave.3.fill", variableValue: volume)
// Symbol effect (iOS 17+)
Image(systemName: "bell.fill")
.symbolEffect(.bounce, value: notificationCount)// Use semantic fonts
Text("Headline")
.font(.headline)
Text("Body text that scales with user preferences")
.font(.body)
// Custom font that respects Dynamic Type
Text("Custom")
.font(.custom("Avenir", size: 17, relativeTo: .body))// Semantic colors that adapt to light/dark mode
Text("Primary")
.foregroundStyle(.primary)
Text("Secondary")
.foregroundStyle(.secondary)
// System materials for blur effects
Rectangle()
.fill(.ultraThinMaterial)
.frame(height: 100)
// Vibrant materials for overlays
Text("Overlay")
.padding()
.background(.regularMaterial, in: RoundedRectangle(cornerRadius: 12))// Standard card shadow
RoundedRectangle(cornerRadius: 16)
.fill(.background)
.shadow(color: .black.opacity(0.1), radius: 8, y: 4)
// Elevated appearance
.shadow(radius: 2, y: 1)
.shadow(radius: 8, y: 4)import SwiftUI
struct FeatureCard: View {
let title: String
let description: String
let systemImage: String
var body: some View {
HStack(spacing: 16) {
Image(systemName: systemImage)
.font(.title)
.foregroundStyle(.blue)
.frame(width: 44, height: 44)
.background(.blue.opacity(0.1), in: Circle())
VStack(alignment: .leading, spacing: 4) {
Text(title)
.font(.headline)
Text(description)
.font(.subheadline)
.foregroundStyle(.secondary)
.lineLimit(2)
}
Spacer()
Image(systemName: "chevron.right")
.foregroundStyle(.tertiary)
}
.padding()
.background(.background, in: RoundedRectangle(cornerRadius: 12))
.shadow(color: .black.opacity(0.05), radius: 4, y: 2)
}
}