home / skills / vladimirbrejcha / ios-ai-skills / apple-hig-designer

apple-hig-designer skill

/apple-hig-designer

This is most likely a fork of the apple-hig-designer skill from jamesrochabrun
npx playbooks add skill vladimirbrejcha/ios-ai-skills --skill apple-hig-designer

Review the files below or copy the command above to add this skill to your agents.

Files (9)
SKILL.md
19.8 KB
---
name: apple-hig-designer
description: Design iOS apps following Apple's Human Interface Guidelines. Generate native components, validate designs, and ensure accessibility compliance for iPhone, iPad, and Apple Watch.
---

# 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**