--- id: jamesrochabrun/skills/apple-hig-designer version: "2549a687" license: MIT install: manual updated: 2026-01-14 --- # apple-hig-designer — Master iOS app design by leveraging Apple's Human Interface Guidelines within your development workflow. This skill equips you with native component libraries, design patterns, and best practices to create interfaces that feel native to the Apple ecosystem. Streamline your design-to-code process with structured guidance on layout, typography, color, and interaction patterns. Publisher: jamesrochabrun · Stars: 187 · Updated: 2026-01-14 Install (manual): `git clone https://github.com/jamesrochabrun/skills` ## SKILL.md # Apple HIG Designer Design beautiful, native iOS apps following Apple's Human Interface Guidelines (HIG). Create accessible, intuitive interfaces with native components, proper typography, semantic colors, and Apple's design principles. ## What This Skill Does Helps you design and build iOS apps that feel native and follow Apple's guidelines: - **Generate iOS Components** - Create SwiftUI and UIKit components - **Validate Designs** - Check compliance with Apple HIG - **Ensure Accessibility** - VoiceOver, Dynamic Type, color contrast - **Apply Design Principles** - Clarity, Deference, Depth - **Use Semantic Colors** - Automatic dark mode support - **Implement Typography** - San Francisco font system - **Follow Spacing** - 8pt grid system and safe areas ## Apple's Design Principles ### 1. Clarity **Make content clear and focused.** Text is legible at every size, icons are precise and lucid, adornments are subtle and appropriate, and a focus on functionality drives the design. ```swift // ✅ Clear, focused content Text("Welcome back, Sarah") .font(.title) .foregroundColor(.primary) // ❌ Unclear, cluttered Text("Welcome back, Sarah!!!") .font(.title) .foregroundColor(.red) .background(.yellow) .overlay(Image(systemName: "star.fill")) ``` ### 2. Deference **UI helps people understand and interact with content, but never competes with it.** The interface defers to content, using a light visual treatment that keeps focus on the content and gives the content room to breathe. ```swift // ✅ Content-focused VStack(alignment: .leading, spacing: 8) { Text("Article Title") .font(.headline) Text("Article content goes here...") .font(.body) .foregroundColor(.secondary) } .padding() // ❌ Distracting UI VStack(spacing: 8) { Text("Article Title") .font(.headline) .foregroundColor(.white) .background(.blue) .border(.red, width: 3) } ``` ### 3. Depth **Visual layers and realistic motion convey hierarchy and help people understand relationships.** Distinct visual layers and realistic motion impart vitality and facilitate understanding. Touch and discoverability heighten delight and enable access to functionality without losing context. ```swift // ✅ Clear depth hierarchy ZStack { Color(.systemBackground) VStack { // Card with elevation CardView() .shadow(radius: 8) } } // Using blur for depth Text("Content") .background(.ultraThinMaterial) ``` ## iOS UI Components ### Navigation Patterns #### 1. Navigation Bar **Top bar for navigation and actions.** ```swift NavigationStack { List { Text("Item 1") Text("Item 2") } .navigationTitle("Title") .navigationBarTitleDisplayMode(.large) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button("Add") { // Action } } } } ``` **Guidelines:** - Use large titles for top-level views - Use inline titles for detail views - Keep actions relevant to current context - Maximum 2-3 toolbar items #### 2. Tab Bar **Bottom navigation for top-level destinations.** ```swift TabView { HomeView() .tabItem { Label("Home", systemImage: "house") } SearchView() .tabItem { Label("Search", systemImage: "magnifyingglass") } ProfileView() .tabItem { Label("Profile", systemImage: "person") } } ``` **Guidelines:** - 3-5 tabs maximum - Use SF Symbols for icons - Labels should be concise (one word) - Never hide or disable tabs - Don't use tab bar with toolbar in same view #### 3. List **Scrollable list of items.** ```swift List { Section("Today") { ForEach(items) { item in NavigationLink { DetailView(item: item) } label: { HStack { Image(systemName: item.icon) .foregroundColor(.accentColor) Text(item.title) } } } } } .listStyle(.insetGrouped) ``` **List Styles:** - `.plain` - Edge-to-edge rows - `.insetGrouped` - Rounded, inset sections (iOS default) - `.sidebar` - For navigation sidebars #### 4. Sheet (Modal) **Present content modally.** ```swift struct ContentView: View { @State private var showSheet = false var body: some View { Button("Show Details") { showSheet = true } .sheet(isPresented: $showSheet) { DetailView() .presentationDetents([.medium, .large]) } } } ``` **Sheet Detents:** - `.medium` - Half screen - `.large` - Full screen - Custom heights available ### Form Controls #### 1. Button **Primary action control.** ```swift // Filled button (primary action) Button("Continue") { // Action } .buttonStyle(.borderedProminent) // Bordered button (secondary action) Button("Cancel") { // Action } .buttonStyle(.bordered) // Plain button (tertiary action) Button("Learn More") { // Action } .buttonStyle(.plain) ``` **Button Hierarchy:** 1. **Prominent** - Primary action (one per screen) 2. **Bordered** - Secondary actions 3. **Plain** - Tertiary actions, links **Guidelines:** - Minimum tap target: 44x44 points - Use verbs for button labels - Make destructive actions require confirmation #### 2. TextField **Text input control.** ```swift @State private var username = "" @State private var password = "" VStack(alignment: .leading, spacing: 16) { // Standard text field TextField("Username", text: $username) .textFieldStyle(.roundedBorder) .textContentType(.username) .textInputAutocapitalization(.never) .autocorrectionDisabled() // Secure field SecureField("Password", text: $password) .textFieldStyle(.roundedBorder) .textContentType(.password) } ``` **Text Content Types:** - `.username` - Username field - `.password` - Password field - `.emailAddress` - Email field - `.telephoneNumber` - Phone number - `.creditCardNumber` - Credit card #### 3. Toggle **Boolean control (switch).** ```swift @State private var isEnabled = false Toggle("Enable notifications", isOn: $isEnabled) .toggleStyle(.switch) ``` **Guidelines:** - Label describes what the toggle controls - Effect should be immediate - Use for binary choices only #### 4. Picker **Selection control.** ```swift @State private var selectedSize = "Medium" let sizes = ["Small", "Medium", "Large"] // Menu style Picker("Size", selection: $selectedSize) { ForEach(sizes, id: \.self) { size in Text(size).tag(size) } } .pickerStyle(.menu) // Segmented style (for 2-5 options) Picker("Size", selection: $selectedSize) { ForEach(sizes, id: \.self) { size in Text(size).tag(size) } } .pickerStyle(.segmented) ``` **Picker Styles:** - `.menu` - Dropdown menu (default) - `.segmented` - Segmented control (2-5 options) - `.wheel` - Scrollable wheel - `.inline` - Inline list (in forms) ### Cards and Containers #### Card View ```swift struct CardView: View { var body: some View { VStack(alignment: .leading, spacing: 12) { Text("Title") .font(.headline) Text("Description goes here with some details about the content.") .font(.subheadline) .foregroundColor(.secondary) .lineLimit(2) Spacer() Button("Action") { // Action } .buttonStyle(.borderedProminent) } .padding() .frame(width: 300, height: 200) .background(Color(.systemBackground)) .cornerRadius(12) .shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 4) } } ``` ## Typography ### San Francisco Font System Apple's system font designed for optimal legibility. ```swift // Dynamic Type text styles Text("Large Title").font(.largeTitle) // 34pt Text("Title").font(.title) // 28pt Text("Title 2").font(.title2) // 22pt Text("Title 3").font(.title3) // 20pt Text("Headline").font(.headline) // 17pt semibold Text("Body").font(.body) // 17pt regular Text("Callout").font(.callout) // 16pt Text("Subheadline").font(.subheadline) // 15pt Text("Footnote").font(.footnote) // 13pt Text("Caption").font(.caption) // 12pt Text("Caption 2").font(.caption2) // 11pt ``` ### Custom Fonts with Dynamic Type ```swift // Custom font that scales with Dynamic Type Text("Custom Text") .font(.custom("YourFont-Regular", size: 17, relativeTo: .body)) ``` ### Font Weights ```swift Text("Light").fontWeight(.light) Text("Regular").fontWeight(.regular) Text("Medium").fontWeight(.medium) Text("Semibold").fontWeight(.semibold) Text("Bold").fontWeight(.bold) Text("Heavy").fontWeight(.heavy) ``` ### Typography Guidelines **Do:** - ✅ Use system font (San Francisco) for consistency - ✅ Support Dynamic Type for accessibility - ✅ Use semantic text styles (.headline, .body, etc.) - ✅ Minimum body text: 17pt - ✅ Line spacing: 120-145% of font size **Don't:** - ❌ Use too many font sizes (stick to system styles) - ❌ Make text smaller than 11pt - ❌ Use all caps for long text - ❌ Disable Dynamic Type ## Colors ### Semantic Colors **Colors that automatically adapt to light/dark mode.** ```swift // UI Element Colors Color(.label) // Primary text Color(.secondaryLabel) // Secondary text Color(.tertiaryLabel) // Tertiary text Color(.quaternaryLabel) // Watermark text Color(.systemBackground) // Primary background Color(.secondarySystemBackground) // Secondary background Color(.tertiarySystemBackground) // Tertiary background Color(.systemFill) // Fill colors Color(.secondarySystemFill) Color(.tertiarySystemFill) Color(.quaternarySystemFill) Color(.separator) // Separator lines Color(.opaqueSeparator) // Non-transparent separator ``` ### System Colors ```swift // Standard system colors (adapt to dark mode) Color(.systemRed) Color(.systemOrange) Color(.systemYellow) Color(.systemGreen) Color(.systemMint) Color(.systemTeal) Color(.systemCyan) Color(.systemBlue) Color(.systemIndigo) Color(.systemPurple) Color(.systemPink) Color(.systemBrown) Color(.systemGray) ``` ### Custom Colors with Dark Mode ```swift // Define adaptive color extension Color { static let customBackground = Color("CustomBackground") } // In Assets.xcassets, create color set with: // - Any Appearance: #FFFFFF // - Dark Appearance: #000000 ``` ### Color Contrast Guidelines **WCAG AA Compliance:** - Normal text: 4.5:1 contrast ratio minimum - Large text (24pt+): 3:1 contrast ratio minimum - UI components: 3:1 contrast ratio **Custom colors:** - Test with Increase Contrast enabled - Aim for 7:1 for critical text - Provide sufficient contrast in both modes ## Spacing and Layout ### 8-Point Grid System **All spacing should be multiples of 8.** ```swift // Spacing values .padding(8) // 8pt .padding(16) // 16pt (standard) .padding(24) // 24pt .padding(32) // 32pt .padding(40) // 40pt .padding(48) // 48pt // Edge-specific padding .padding(.horizontal, 16) .padding(.vertical, 24) .padding(.top, 16) .padding(.bottom, 16) ``` ### Safe Areas **Respect device safe areas.** ```swift // Content within safe area (default) VStack { Text("Content") } // Extend beyond safe area VStack { Color.blue } .ignoresSafeArea() // Extend top only VStack { Color.blue } .ignoresSafeArea(edges: .top) ``` ### Touch Targets **Minimum interactive size: 44x44 points.** ```swift Button("Tap") { // Action } .frame(minWidth: 44, minHeight: 44) ``` ### Spacing Guidelines ```swift // Component spacing VStack(spacing: 8) { // Tight spacing Text("Line 1") Text("Line 2") } VStack(spacing: 16) { // Standard spacing Text("Section 1") Text("Section 2") } VStack(spacing: 24) { // Loose spacing SectionView() SectionView() } ``` ## Accessibility ### VoiceOver Support **Screen reader for blind and low-vision users.** ```swift // Accessible label Image(systemName: "heart.fill") .accessibilityLabel("Favorite") // Accessible value Slider(value: $volume) .accessibilityLabel("Volume") .accessibilityValue("\(Int(volume * 100))%") // Accessible hint Button("Share") { share() } .accessibilityHint("Shares this item with others") // Group elements HStack { Image(systemName: "person") Text("John Doe") } .accessibilityElement(children: .combine) // Hidden from VoiceOver Image("decorative") .accessibilityHidden(true) ``` ### Dynamic Type **Support user's preferred text size.** ```swift // Automatically supported with system fonts Text("This text scales") .font(.body) // Limit scaling (if necessary) Text("This text has limits") .font(.body) .dynamicTypeSize(...DynamicTypeSize.xxxLarge) // Custom font with Dynamic Type Text("Custom font") .font(.custom("YourFont", size: 17, relativeTo: .body)) ``` ### Color Blindness **Design for color-blind users.** ```swift // Don't rely on color alone HStack { Image(systemName: "checkmark.circle.fill") .foregroundColor(.green) Text("Success") } // Not just color Circle() .fill(.green) // ❌ Color only // Better with shape/icon HStack { Image(systemName: "checkmark.circle.fill") Circle().fill(.green) } // ✅ Color + shape ``` ### Reduce Motion **Respect user's motion preferences.** ```swift @Environment(\.accessibilityReduceMotion) var reduceMotion var animation: Animation { reduceMotion ? .none : .spring() } Button("Animate") { withAnimation(animation) { // Animate } } ``` ### Increase Contrast **Support high contrast mode.** ```swift @Environment(\.colorSchemeContrast) var contrast var textColor: Color { contrast == .increased ? .primary : .secondary } Text("Content") .foregroundColor(textColor) ``` ## Dark Mode **Support both light and dark appearances.** ### Automatic Support ```swift // Use semantic colors (automatic) Color(.label) // Adapts automatically Color(.systemBackground) // Adapts automatically ``` ### Testing Dark Mode ```swift // Preview both modes struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() .preferredColorScheme(.light) ContentView() .preferredColorScheme(.dark) } } ``` ### Dark Mode Guidelines **Do:** - ✅ Use semantic colors - ✅ Test with Increase Contrast - ✅ Test with Reduce Transparency - ✅ Ensure sufficient contrast in both modes **Don't:** - ❌ Use pure black (#000000) - use systemBackground - ❌ Invert colors automatically - ❌ Assume user preference ## SF Symbols **Apple's icon system (3000+ symbols).** ```swift // Basic symbol Image(systemName: "heart") // Colored symbol Image(systemName: "heart.fill") .foregroundColor(.red) // Sized symbol Image(systemName: "heart") .imageScale(.large) // Font-based sizing Image(systemName: "heart") .font(.title) // Multicolor symbols Image(systemName: "person.crop.circle.fill.badge.checkmark") .symbolRenderingMode(.multicolor) // Hierarchical rendering Image(systemName: "heart.fill") .symbolRenderingMode(.hierarchical) .foregroundColor(.red) ``` ### SF Symbols Guidelines - Use system symbols when available - Maintain visual weight consistency - Use multicolor for semantic meaning - Size appropriately for context ## App Icons ### Icon Sizes ``` iOS: - 1024x1024 (App Store) - 180x180 (iPhone @3x) - 120x120 (iPhone @2x) - 167x167 (iPad Pro) - 152x152 (iPad @2x) watchOS: - 1024x1024 (App Store) - 196x196 (49mm) - 216x216 (45mm) ``` ### Icon Design Guidelines **Do:** - ✅ Use simple, recognizable shapes - ✅ Fill entire icon space - ✅ Test on device (not just mockups) - ✅ Use consistent visual style **Don't:** - ❌ Include text (very small) - ❌ Use photos - ❌ Replicate Apple hardware - ❌ Use translucency ## Animation and Motion ### Standard Animations ```swift // Spring animation (natural, bouncy) withAnimation(.spring()) { offset = 100 } // Linear animation withAnimation(.linear(duration: 0.3)) { opacity = 0 } // Ease in/out withAnimation(.easeInOut(duration: 0.3)) { scale = 1.2 } ``` ### Gesture-Driven ```swift @State private var offset = CGSize.zero var body: some View { Circle() .offset(offset) .gesture( DragGesture() .onChanged { value in offset = value.translation } .onEnded { _ in withAnimation(.spring()) { offset = .zero } } ) } ``` ### Motion Guidelines - Keep animations under 0.3 seconds - Use spring animations for interactive elements - Respect Reduce Motion setting - Provide visual feedback for all interactions ## Best Practices ### Navigation - **Hierarchical** - Use NavigationStack for drilldown - **Flat** - Use TabView for peer destinations - **Content-Driven** - Use for media apps ### Feedback - **Visual** - Highlight on tap - **Haptic** - Use UIImpactFeedbackGenerator - **Audio** - Use system sounds sparingly ### Loading States ```swift struct LoadingView: View { var body: some View { VStack { ProgressView() .scaleEffect(1.5) Text("Loading...") .font(.caption) .foregroundColor(.secondary) .padding(.top) } } } ``` ### Error States ```swift struct ErrorView: View { let message: String let retry: () -> Void var body: some View { VStack(spacing: 16) { Image(systemName: "exclamationmark.triangle") .font(.system(size: 48)) .foregroundColor(.orange) Text("Something went wrong") .font(.headline) Text(message) .font(.subheadline) .foregroundColor(.secondary) .multilineTextAlignment(.center) Button("Try Again") { retry() } .buttonStyle(.borderedProminent) } .padding() } } ``` ### Empty States ```swift struct EmptyStateView: View { var body: some View { VStack(spacing: 16) { Image(systemName: "tray") .font(.system(size: 64)) .foregroundColor(.secondary) Text("No Items") .font(.title2) Text("Your items will appear here") .font(.subheadline) .foregroundColor(.secondary) Button("Add Item") { // Action } .buttonStyle(.borderedProminent) } } } ``` ## Platform Considerations ### iPhone - Design for various sizes (SE, Pro, Pro Max) - Support portrait and landscape - Use safe areas for notch/Dynamic Island - Consider one-handed use ### iPad - Support multitasking (Split View, Slide Over) - Use sidebars for navigation - Adapt to larger screen (don't just scale) - Consider keyboard shortcuts - Support external displays ### Apple Watch - Glanceable information - Large touch targets (>44pt) - Minimal interaction required - Use Digital Crown for scrolling - Support Always-On display ## Resources - [Apple HIG Official](https://developer.apple.com/design/human-interface-guidelines/) - [SF Symbols App](https://developer.apple.com/sf-symbols/) - [WWDC Videos](https://developer.apple.com/videos/) - [Apple Design Resources](https://developer.apple.com/design/resources/) --- **"Design is not just what it looks like and feels like. Design is how it works." - Steve Jobs** [View on SkillFed](https://skillfed.io/jamesrochabrun/skills/apple-hig-designer) · [View on GitHub](https://github.com/jamesrochabrun/skills)