| 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.
Text("Welcome back, Sarah")
.font(.title)
.foregroundColor(.primary)
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.
VStack(alignment: .leading, spacing: 8) {
Text("Article Title")
.font(.headline)
Text("Article content goes here...")
.font(.body)
.foregroundColor(.secondary)
}
.padding()
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.
ZStack {
Color(.systemBackground)
VStack {
CardView()
.shadow(radius: 8)
}
}
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") {
}
}
}
}
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.
Button("Continue") {
}
.buttonStyle(.borderedProminent)
Button("Cancel") {
}
.buttonStyle(.bordered)
Button("Learn More") {
}
.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) {
TextField("Username", text: $username)
.textFieldStyle(.roundedBorder)
.textContentType(.username)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
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"]
Picker("Size", selection: $selectedSize) {
ForEach(sizes, id: \.self) { size in
Text(size).tag(size)
}
}
.pickerStyle(.menu)
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") {
}
.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.
Text("Large Title").font(.largeTitle)
Text("Title").font(.title)
Text("Title 2").font(.title2)
Text("Title 3").font(.title3)
Text("Headline").font(.headline)
Text("Body").font(.body)
Text("Callout").font(.callout)
Text("Subheadline").font(.subheadline)
Text("Footnote").font(.footnote)
Text("Caption").font(.caption)
Text("Caption 2").font(.caption2)
Custom Fonts 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.
Color(.label)
Color(.secondaryLabel)
Color(.tertiaryLabel)
Color(.quaternaryLabel)
Color(.systemBackground)
Color(.secondarySystemBackground)
Color(.tertiarySystemBackground)
Color(.systemFill)
Color(.secondarySystemFill)
Color(.tertiarySystemFill)
Color(.quaternarySystemFill)
Color(.separator)
Color(.opaqueSeparator)
System Colors
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
extension Color {
static let customBackground = Color("CustomBackground")
}
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.
.padding(8)
.padding(16)
.padding(24)
.padding(32)
.padding(40)
.padding(48)
.padding(.horizontal, 16)
.padding(.vertical, 24)
.padding(.top, 16)
.padding(.bottom, 16)
Safe Areas
Respect device safe areas.
VStack {
Text("Content")
}
VStack {
Color.blue
}
.ignoresSafeArea()
VStack {
Color.blue
}
.ignoresSafeArea(edges: .top)
Touch Targets
Minimum interactive size: 44x44 points.
Button("Tap") {
}
.frame(minWidth: 44, minHeight: 44)
Spacing Guidelines
VStack(spacing: 8) {
Text("Line 1")
Text("Line 2")
}
VStack(spacing: 16) {
Text("Section 1")
Text("Section 2")
}
VStack(spacing: 24) {
SectionView()
SectionView()
}
Accessibility
VoiceOver Support
Screen reader for blind and low-vision users.
Image(systemName: "heart.fill")
.accessibilityLabel("Favorite")
Slider(value: $volume)
.accessibilityLabel("Volume")
.accessibilityValue("\(Int(volume * 100))%")
Button("Share") {
share()
}
.accessibilityHint("Shares this item with others")
HStack {
Image(systemName: "person")
Text("John Doe")
}
.accessibilityElement(children: .combine)
Image("decorative")
.accessibilityHidden(true)
Dynamic Type
Support user's preferred text size.
Text("This text scales")
.font(.body)
Text("This text has limits")
.font(.body)
.dynamicTypeSize(...DynamicTypeSize.xxxLarge)
Text("Custom font")
.font(.custom("YourFont", size: 17, relativeTo: .body))
Color Blindness
Design for color-blind users.
HStack {
Image(systemName: "checkmark.circle.fill")
.foregroundColor(.green)
Text("Success")
}
Circle()
.fill(.green)
HStack {
Image(systemName: "checkmark.circle.fill")
Circle().fill(.green)
}
Reduce Motion
Respect user's motion preferences.
@Environment(\.accessibilityReduceMotion) var reduceMotion
var animation: Animation {
reduceMotion ? .none : .spring()
}
Button("Animate") {
withAnimation(animation) {
}
}
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
Color(.label)
Color(.systemBackground)
Testing Dark Mode
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).
Image(systemName: "heart")
Image(systemName: "heart.fill")
.foregroundColor(.red)
Image(systemName: "heart")
.imageScale(.large)
Image(systemName: "heart")
.font(.title)
Image(systemName: "person.crop.circle.fill.badge.checkmark")
.symbolRenderingMode(.multicolor)
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
withAnimation(.spring()) {
offset = 100
}
withAnimation(.linear(duration: 0.3)) {
opacity = 0
}
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") {
}
.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