apple-hig-designer

Native iOS design following Apple's Human Interface Guidelines with component generation and accessibility validation. Generates SwiftUI and UIKit components aligned with Apple's design principles of clarity, deference, and depth Validates designs against HIG compliance and ensures accessibility support including VoiceOver, Dynamic Type, and color contrast standards Covers navigation patterns (tab bars, navigation stacks, sheets), form controls (buttons, text fields, toggles, pickers), and semantic colors with automatic dark mode adaptation Implements 8-point grid spacing, San Francisco typography system, and 44x44 minimum touch targets across iPhone, iPad, and Apple Watch platforms Includes guidance on motion, SF Symbols, app icons, error states, and platform-specific considerations for multitasking and Always-On displays

INSTALLATION
npx skills add https://github.com/jamesrochabrun/skills --skill apple-hig-designer
Run in your project or agent environment. Adjust flags if your CLI version differs.

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.

// ✅ 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.

// ✅ 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.

// ✅ 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.

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.

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.

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.

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.

// 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:

  • Prominent - Primary action (one per screen)
  • Bordered - Secondary actions
  • 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.

@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).

@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.

@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

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.

// 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

// Custom font that scales with Dynamic Type

Text("Custom Text")

    .font(.custom("YourFont-Regular", size: 17, relativeTo: .body))

Font Weights

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.

// 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

// 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

// 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.

// 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.

// 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.

Button("Tap") {

    // Action

}

.frame(minWidth: 44, minHeight: 44)

Spacing Guidelines

// 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.

// 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.

// 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.

// 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.

@Environment(\.accessibilityReduceMotion) var reduceMotion

var animation: Animation {

    reduceMotion ? .none : .spring()

}

Button("Animate") {

    withAnimation(animation) {

        // Animate

    }

}

Increase Contrast

Support high contrast mode.

@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

// Use semantic colors (automatic)

Color(.label)                // Adapts automatically

Color(.systemBackground)     // Adapts automatically

Testing Dark Mode

// 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).

// 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

// 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

@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

struct LoadingView: View {

    var body: some View {

        VStack {

            ProgressView()

                .scaleEffect(1.5)

            Text("Loading...")

                .font(.caption)

                .foregroundColor(.secondary)

                .padding(.top)

        }

    }

}

Error States

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

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

"Design is not just what it looks like and feels like. Design is how it works." - Steve Jobs

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card