Reference — Comprehensive Apple Human Interface Guidelines covering colors (semantic, custom, patterns), backgrounds (material hierarchy, dynamic), typography (built-in styles, custom fonts, Dynamic Type), SF Symbols (rendering modes, color, axiom-localization), Dark Mode, accessibility, and platform-specific considerations
Provides comprehensive Apple Human Interface Guidelines reference for design, colors, typography, layout, and accessibility.
npx claudepluginhub charleswiltgen/axiomThis skill inherits all available tools. When active, it can use any tool Claude has access to.
The Human Interface Guidelines (HIG) define Apple's design philosophy and provide concrete guidance for creating intuitive, accessible, platform-appropriate experiences across all Apple devices.
Every design decision should support these principles:
1. Clarity Content is paramount. Interface elements should defer to content, not compete with it. Every element has a purpose, unnecessary complexity is eliminated, and users should immediately know what they can do without extensive instructions.
2. Consistency Apps use standard UI elements and familiar patterns. Navigation follows platform conventions, gestures work as expected, and components appear in expected locations. This familiarity reduces cognitive load.
3. Deference The UI should not distract from essential content. Use subtle backgrounds, receding navigation when not needed, restrained branding, and let content be the hero.
From Apple HIG: "Deference makes an app beautiful by ensuring the content stands out while the surrounding visual elements do not compete with it."
From WWDC25: "A systematic approach means designing with intention at every level, ensuring that all elements, from the tiniest control to the largest surface, are considered in relation to the whole."
axiom-hig for quick decisions and checklistsaxiom-liquid-glass for iOS 26 material implementationaxiom-liquid-glass-ref for iOS 26 app-wide adoptionaxiom-accessibility-diag for accessibility troubleshootingInstead of hardcoded color values, use semantic colors that describe the purpose of a color rather than its appearance. Semantic colors automatically adapt to light/dark mode and accessibility settings.
Key insight from WWDC19: "Think of Dark Mode as having the lights dimmed rather than everything being flipped inside out." Colors are NOT simply inverted—table row backgrounds are lighter in both modes.
Four semantic label levels for text and symbols, each progressively less prominent:
| Style | Semantic Color | Usage |
|---|---|---|
.primary | label | Titles, most prominent text |
.secondary | secondaryLabel | Subtitles, less prominent |
.tertiary | tertiaryLabel | Placeholder text |
.quaternary | quaternaryLabel | Disabled text |
Text("Title").foregroundStyle(.primary) // Black in Light, white in Dark
Text("Subtitle").foregroundStyle(.secondary)
Background colors come in two sets — ungrouped (standard lists) and grouped (iOS Settings style):
| Level | Ungrouped | Grouped |
|---|---|---|
| Primary | .systemBackground | .systemGroupedBackground |
| Secondary | .secondarySystemBackground | .secondarySystemGroupedBackground |
| Tertiary | .tertiarySystemBackground | .tertiarySystemGroupedBackground |
Ungrouped: pure white/black in Light/Dark. Grouped: light gray/dark in Light/Dark.
// Standard list → ungrouped backgrounds
List { Text("Item") }
.background(Color(.systemBackground))
// Settings-style list → grouped backgrounds
List { Section("Section") { Text("Item") } }
.listStyle(.grouped)
There are actually two sets of background colors for layering interfaces:
Why this matters:
In Light Mode, simple drop shadows create visual separation. In Dark Mode, drop shadows are less effective, so the system uses lighter colors for elevated content.
Example: iPad multitasking:
Critical: Some darker colors may not contrast well when elevated. Always test designs in elevated state. Semi-opaque fill and separator colors adapt gracefully.
Tint colors are dynamic - they have variants for Light and Dark modes:
// Tint color automatically adapts
Button("Primary Action") {
// action
}
.tint(.blue)
// Gets lighter in Dark Mode, darker in Light Mode
Custom tint colors: When creating custom tint colors, select colors that work well in both modes. Use a contrast calculator to aim for 4.5:1 or higher contrast ratio. Colors that work in Light Mode may have insufficient contrast in Dark Mode.
Fill colors are semi-transparent to contrast well against variable backgrounds:
// System fill colors
Color(.systemFill)
Color(.secondarySystemFill)
Color(.tertiarySystemFill)
Color(.quaternarySystemFill)
When to use: Controls, buttons, and interactive elements that need to appear above dynamic backgrounds.
// Standard separator (semi-transparent)
Color(.separator)
// Opaque separator
Color(.opaqueSeparator)
Opaque separators are used when transparency would create undesirable results (e.g., intersecting grid lines where overlapping semi-transparent colors create optical illusions).
Apple's explicit guidance:
"In rare cases, consider using only a dark appearance in the interface. For example, it can make sense for an app that enables immersive media viewing to use a permanently dark appearance that lets the UI recede and helps people focus on the media."
Examples from Apple's apps:
| App | Background | Rationale |
|---|---|---|
| Music | Dark | Album art should be visual focus |
| Photos | Dark | Images are hero content |
| Clock | Dark | Nighttime use, instrument feel |
| Stocks | Dark | Data visualization, charts |
| Camera | Dark | Reduces distraction during capture |
For all other apps: Support both Light and Dark modes via system backgrounds.
When you need custom colors:
// Use custom color from asset catalog
Color("BrandAccent")
// Automatically uses correct variant
San Francisco (SF): The system sans-serif font family.
New York (NY): System serif font family for editorial content.
Both available as variable fonts with seamless weight transitions.
From Apple HIG: "Avoid light font weights. Prefer Regular, Medium, Semibold, or Bold weights instead of Ultralight, Thin, or Light."
Why: Light weights have legibility issues, especially at small sizes, in bright lighting, or for users with visual impairments.
Hierarchy:
// Headers - Bold weight for prominence
Text("Header")
.font(.title.weight(.bold))
// Subheaders - Semibold
Text("Subheader")
.font(.title2.weight(.semibold))
// Body - Regular or Medium
Text("Body text")
.font(.body)
// Captions - Regular (never Light)
Text("Caption")
.font(.caption)
Use built-in text styles for automatic hierarchy and Dynamic Type support:
.font(.largeTitle) .font(.title) .font(.title2)
.font(.title3) .font(.headline) .font(.body)
.font(.callout) .font(.subheadline) .font(.footnote)
.font(.caption) .font(.caption2)
All text styles scale automatically with Dynamic Type.
Requirement: Apps must support text scaling of at least 200% (iOS, iPadOS) or 140% (watchOS).
Implementation:
// ✅ CORRECT - Scales automatically
Text("Hello")
.font(.body)
// ❌ WRONG - Fixed size, doesn't scale
Text("Hello")
.font(.system(size: 17))
Layout considerations:
Not all content scales equally: Prioritize what users actually care about. Secondary elements like tab titles shouldn't grow as much as primary content.
When using custom fonts:
If your custom font is thin: Increase size by ~2 points when pairing with uppercase Latin text.
Loose leading: Wide columns (easier to track to next line) Tight leading: Constrained height (avoid for 3+ lines)
// Adjust leading for specific layouts
Text("Long content...")
.lineSpacing(8) // Add space between lines
From WWDC25: "There's a quiet geometry to how our shapes fit together, driven by concentricity. By aligning radii and margins around a shared center, shapes can comfortably nest within each other."
Constant corner radius regardless of size:
RoundedRectangle(cornerRadius: 12)
Use when: You need a specific, unchanging corner radius.
Radius is half the container's height:
Capsule()
Use when: You want shapes that adapt to content while maintaining rounded ends. Perfect for buttons, pills, and controls.
Found throughout iOS 26: Sliders, switches, grouped table views, tab bars, navigation bars.
Calculate radius by subtracting padding from parent's radius:
.containerRelativeShape(.roundedRectangle)
Use when: Nesting shapes within containers to maintain visual harmony.
Hardware ↔ Software harmony: Apple's hardware features consistent bezel curvature. The same precision now guides UI, with curvature, size, and proportion aligning to create unified rhythm between what you hold and what you see.
Example of concentricity:
Window (rounded corners)
├─ Sheet (concentric to window)
│ ├─ Card (concentric to sheet)
│ │ └─ Button (concentric to card)
iOS:
macOS:
To preserve optical balance, views are:
Example: Asymmetric icons may need padding adjustments for optical centering rather than geometric centering.
Materials allow background content to show through, creating visual depth and hierarchy.
Choosing thickness:
// Apply material
.background(.ultraThinMaterial)
.background(.thinMaterial)
.background(.regularMaterial)
.background(.thickMaterial)
Key principle: Use vibrant colors on top of materials for legibility. Solid colors can get muddy depending on background context. Vibrancy maintains contrast regardless of background.
// Vibrant text on material
VStack {
Text("Primary")
.foregroundStyle(.primary) // Vibrant
Text("Secondary")
.foregroundStyle(.secondary) // Vibrant
}
.background(.regularMaterial)
Purpose: Creates a distinct functional layer for controls and navigation, floating above content.
Two variants:
Regular Liquid Glass
Clear Liquid Glass
Modals & Sheets (iOS 26+): Sheets, alerts, and popovers automatically adopt Liquid Glass with Xcode 26 — remove custom .presentationBackground() or UIBlurEffect backgrounds. System handles material, concentric corner radius, and morphing transitions. Use elevated semantic colors for modal content backgrounds, not Liquid Glass on the sheet body.
Cross-reference: For full Liquid Glass implementation patterns (sheets, alerts, popovers, morphing transitions), see axiom-liquid-glass-ref. For decision trees, see axiom-liquid-glass.
Place items to convey their relative importance:
From Apple HIG: "Make essential information easy to find by giving it sufficient space and avoid obscuring it with nonessential details."
Group related items using:
Ensure content and controls remain clearly distinct through Liquid Glass material and scroll edge effects.
"Extend content to fill the screen or window" with backgrounds and artwork reaching display edges.
Background extension views: Use when content doesn't naturally span the full window.
// Content extends to edges
VStack {
FullWidthImage()
.ignoresSafeArea() // Extends to screen edges
}
Safe Areas: Rectangular regions unobstructed by:
Layout Guides: Define rectangular regions for positioning and spacing content with:
Key principle: "Respect key display and system features in each platform."
// Respect safe areas
VStack {
Text("Content")
}
.safeAreaInset(edge: .bottom) {
BottomBar()
}
"Align components with one another to make them easier to scan."
Grid alignment:
Design layouts that:
Requirements:
WCAG Level AA standards:
Implementation:
// ✅ Use semantic colors (automatic contrast)
Text("Label").foregroundStyle(.primary)
// ❌ Custom colors may fail contrast
Text("Label").foregroundStyle(.gray) // Check with calculator
High contrast mode: Provide higher contrast color schemes when "Increase Contrast" accessibility setting is enabled.
Test in both Light and Dark modes.
Critical: "Convey information with more than color alone" to support colorblind users.
Solutions:
Example:
// ❌ Only color indicates status
Circle().fill(isActive ? .green : .red)
// ✅ Shape + color
HStack {
Image(systemName: isActive ? "checkmark.circle.fill" : "xmark.circle.fill")
Text(isActive ? "Active" : "Inactive")
}
.foregroundStyle(isActive ? .green : .red)
Describe interface and content for VoiceOver accessibility:
Button {
share()
} label: {
Image(systemName: "square.and.arrow.up")
}
.accessibilityLabel("Share")
For video/audio content, provide:
Pair audio signals with:
Touch targets:
Gestures:
Assistive technologies:
Respect "Reduce Motion":
// Check Reduce Motion setting
@Environment(\.accessibilityReduceMotion) var reduceMotion
var body: some View {
content
.animation(reduceMotion ? nil : .spring(), value: isExpanded)
}
Offer adjustable difficulty levels.
Prioritize comfort:
Purposeful Animation: "Add motion purposefully, supporting the experience without overshadowing it."
Avoid gratuitous animations that distract or cause discomfort. Motion should enhance rather than dominate the interface.
Make motion optional. Supplement visual feedback with haptics and audio to communicate important information, ensuring all users can understand your interface regardless of motion preferences.
Design animations aligned with user expectations and gestures. Feedback should be:
Avoid animating frequent UI interactions. Standard system elements already include subtle animations, so custom elements shouldn't add unnecessary motion to common actions.
"Let people cancel motion" by not forcing them to wait for animations to complete before proceeding, especially for repeated interactions.
// ✅ Allow immediate tap, don't block on animation
Button("Next") {
withAnimation(.easeOut(duration: 0.2)) {
showNext = true
}
}
// User can tap again immediately, not forced to wait
SwiftUI provides animation capabilities; WatchKit offers WKInterfaceImage for layout animations and sequences.
6,900+ vector symbols that match San Francisco font, scale with Dynamic Type, and adapt to Bold Text and Dark Mode automatically. Nine weights, three scales, four rendering modes, and 12+ animation effects.
For comprehensive coverage of rendering modes (Monochrome, Hierarchical, Palette, Multicolor), symbol effects (Bounce, Pulse, Wiggle, Draw On/Off), and custom symbol authoring, see
axiom-sf-symbols(decision trees) andaxiom-sf-symbols-ref(complete API).
Design principles: Recognizable, simplified designs with familiar visual metaphors. Maintain uniform size, detail level, stroke thickness, and perspective. Match icon weight with adjacent text. Adjust padding for optical centering when visual weight is asymmetric.
Format: Use PDF or SVG for automatic scaling. System components handle selected states automatically.
From WWDC25: "A pencil might suggest annotate, and a checkmark can look like confirm—making actions like Select or Edit easy to misread. When there's no clear shorthand, a text label is always the better choice."
Use icons when:
Use text when:
Always provide alternative text labels enabling VoiceOver descriptions:
Image(systemName: "star.fill")
.accessibilityLabel("Favorite")
Consistency and Familiarity: "People expect most gestures to work the same regardless of their current context." Standard gestures like tap, swipe, and drag should perform their expected functions across platforms.
Responsive Feedback: "Handle gestures as responsively as possible" and provide immediate feedback during gesture performance so users can predict outcomes.
Basic gestures supported across all platforms (though precise movements vary by device):
Minimum touch target sizes:
| Platform | Minimum Size | Spacing |
|---|---|---|
| iOS/iPadOS | 44x44 points | 12-24pt padding |
| macOS | Varies by control | System spacing |
| watchOS | System controls | Optimized for small screen |
| tvOS | Large (focus model) | 60pt+ spacing |
// ✅ Adequate touch target
Button("Tap") { }
.frame(minWidth: 44, minHeight: 44)
// ❌ Too small
Button("Tap") { }
.frame(width: 20, height: 20) // Fails accessibility
Custom gestures should only be implemented when necessary and must be:
Warning: Don't replace standard gestures with custom ones. Shortcuts should supplement, not replace, familiar interactions.
Critical: "Give people more than one way to interact with your app." Never assume users can perform specific gestures.
Provide alternatives:
// ✅ Swipe action + button alternative
.swipeActions {
Button("Delete", role: .destructive) {
delete()
}
}
.contextMenu {
Button("Delete", role: .destructive) {
delete()
}
}
Mandatory for: iOS, iPadOS, tvOS Not required for: macOS, axiom-visionOS, watchOS
Design principle: "Design a launch screen that's nearly identical to the first screen of your app or game" to avoid jarring visual transitions.
Minimize branding:
No text:
Match appearance:
// Launch screen matches first screen
// Transitions smoothly without flash
Onboarding is a separate experience that follows the launch phase. Provides "a high-level view of your app or game" and can include a splash screen if needed.
When to use: Only when you have meaningful context to communicate to new users.
What onboarding can include:
Timeline:
Tab Bar Guidelines:
TabView with Tab for adaptationNavigation Bar Guidelines:
prefersLargeTitles) for top-level views only; inline for pushed views... menu for additionalSystem integration: Widgets, Home Screen quick actions, Spotlight, Shortcuts, Activity views
Extends iOS with larger display, sidebar navigation, split view, pointer/trackpad, arbitrary windows (iOS 26+). Don't just scale iOS layouts — leverage sidebars and split views.
Pointer-first, keyboard-centric. Dense layouts, smaller controls than iOS. Multiple windows, menu bar, contextual menus, keyboard shortcuts essential. Controls: Mini/Small/Medium → rounded rectangles, Large/X-Large → capsules.
Very small display — glanceable, minimal interaction. Full-bleed content, minimal padding, Digital Crown interactions, complications for watch faces. Always-on display consideration.
Adapting from iPad/iOS: Replace sidebars with page-based flow. Convert swipe/pinch to Digital Crown rotation. Use opacity/spacing for hierarchy (no materials/Liquid Glass). Complications replace dashboards. @State/@Environment reuse well; view hierarchy must be rewritten.
10-foot viewing distance, focus-based navigation, gestural remote. Large touch targets, prominent focus states, limited text input, directional navigation.
Focus Engine: tvOS uses a UIKit Focus Engine for hardware navigation that coexists with SwiftUI's @FocusState. The Focus Engine is the ultimate authority — @FocusState assignments are ignored if the Focus Engine considers a view unfocusable. Use UIFocusGuide to bridge navigation gaps between isolated views.
TVUIKit: tvOS-exclusive components — TVPosterView (parallax focus effects), TVDigitEntryViewController (PIN entry). No SwiftUI equivalents exist; bridge via UIViewRepresentable.
Text input: Standard text fields trigger a fullscreen system keyboard. For better UX, use the shadow input pattern (Button UI + hidden CocoaTextField). See axiom-tvos for implementation details.
Storage: No persistent local storage. All local files are cache that the system deletes. See axiom-tvos for data strategy.
Spatial computing with glass materials, 3D layouts, depth. Comfortable viewing depth, avoid head-anchored content, center content in field of view.
Welcoming language requirements:
Avoid phrases with oppressive origins (e.g., "peanut gallery").
Exercise caution with humor — it's subjective and difficult to translate across cultures.
Portraying human diversity:
Avoiding assumptions:
Best practices:
Recognize:
Include:
Prepare software for:
Cultural color awareness:
Use plain language and avoid stereotypes to facilitate smoother localization.
Voice & Tone: Maintain consistent brand personality through written communication.
Visual Elements:
Most critical guidance — restraint:
Defer to content: "Using screen space for an element that does nothing but display a brand asset can mean there's less room for the content people care about."
Logo minimalism: "Resist the temptation to display your logo throughout your app or game unless it's essential for providing context."
Familiar patterns: Maintain standard UI behaviors and component placement even with stylized designs to keep interfaces approachable.
Launch screen caution: Avoid using launch screens for branding since they disappear too quickly; consider onboarding screens instead for brand integration.
Do:
Don't:
Apple trademarks cannot appear in your app name or images—consult Apple's official trademark guidelines.
Symptom: App Store rejection for accessibility violations, or colors don't meet WCAG standards.
Diagnosis: Test with Accessibility Inspector, contrast calculators, both Light/Dark modes, and Increase Contrast enabled. See Accessibility > Vision section above for contrast ratio requirements.
Solution:
// ❌ Custom gray may fail contrast
Text("Label").foregroundStyle(.gray)
// ✅ Semantic colors (automatic compliance)
Text("Label").foregroundStyle(.secondary)
// ✅ Verified custom color (~8:1 on white, WCAG AAA)
Text("Label").foregroundStyle(Color(red: 0.25, green: 0.25, blue: 0.25))
Symptom: Users report difficult tapping, App Store accessibility rejection.
Diagnosis:
// Check button size
Button("Tap") { }
.frame(width: 30, height: 30) // ❌ Too small
Solution:
// ✅ Expand touch target to minimum 44x44
Button("Tap") { }
.frame(minWidth: 44, minHeight: 44)
// ✅ Alternative: Add padding
Button("Tap") { }
.padding() // System adds appropriate padding
Symptom: Colors look wrong in Dark Mode, insufficient contrast.
Diagnosis:
Solution:
// ❌ PROBLEM: Hardcoded white text
Text("Label").foregroundStyle(.white)
// Invisible in Light Mode
// ✅ SOLUTION: Semantic color
Text("Label").foregroundStyle(.primary)
// Black in Light, white in Dark
// ✅ ALTERNATIVE: Asset catalog color with variants
Text("Label").foregroundStyle(Color("BrandText"))
// Define in Assets.xcassets with Light/Dark variants
Symptom: Text hard to read, especially at small sizes or in bright lighting.
Diagnosis:
Text("Headline")
.font(.system(size: 17, weight: .ultralight)) // ❌ Too light
Solution:
// ✅ Use Regular minimum
Text("Headline")
.font(.system(size: 17, weight: .regular))
// ✅ Better: Use system text styles
Text("Headline")
.font(.headline) // Automatically uses appropriate weight
Symptom: Text doesn't scale when user changes text size in Settings.
// ❌ Fixed size doesn't scale
Text("Label").font(.system(size: 17))
// ✅ Text styles scale automatically
Text("Label").font(.body)
// ✅ Custom font with scaling
Text("Label").font(.custom("CustomFont", size: 17, relativeTo: .body))
Symptom: Users with motion sensitivity experience discomfort.
Diagnosis:
Solution:
// ✅ Check Reduce Motion setting
@Environment(\.accessibilityReduceMotion) var reduceMotion
var body: some View {
content
.animation(reduceMotion ? nil : .spring(), value: isExpanded)
}
// ✅ Alternative: Simpler animation
.animation(reduceMotion ? .linear(duration: 0.1) : .spring(), value: isExpanded)
Symptom: VoiceOver announces unhelpful information like "Button" instead of action.
Diagnosis:
// ❌ Image button without label
Button {
share()
} label: {
Image(systemName: "square.and.arrow.up")
}
// VoiceOver says: "Button"
Solution:
// ✅ Add accessibility label
Button {
share()
} label: {
Image(systemName: "square.and.arrow.up")
}
.accessibilityLabel("Share")
// VoiceOver says: "Share, Button"
Symptom: Colorblind users can't distinguish status.
Diagnosis:
// ❌ Only color indicates state
Circle()
.fill(isComplete ? .green : .red)
Solution:
// ✅ Use shape + color + text
HStack {
Image(systemName: isComplete ? "checkmark.circle.fill" : "xmark.circle.fill")
Text(isComplete ? "Complete" : "Incomplete")
}
.foregroundStyle(isComplete ? .green : .red)
Symptom: App Store rejects launch screen with logo or text.
Diagnosis:
Solution:
// ❌ Launch screen with logo (rejected)
// Launch.storyboard contains app logo
// ✅ Launch screen matches first screen (approved)
// Launch.storyboard shows same background/layout as first screen
// No text, no logos, minimal branding
// Move branding to onboarding screen instead
Symptom: Users confused by app-specific dark mode setting, double settings.
Diagnosis:
Solution:
// ❌ App-specific appearance toggle
.preferredColorScheme(userPreference == .dark ? .dark : .light)
// ✅ Respect system preference
// Remove custom toggle, use system preference
// Let iOS Settings control appearance
WWDC: 356, 2019-808
Docs: /design/human-interface-guidelines, /design/human-interface-guidelines/color, /design/human-interface-guidelines/dark-mode, /design/human-interface-guidelines/materials, /design/human-interface-guidelines/typography, /design/human-interface-guidelines/layout, /design/human-interface-guidelines/accessibility, /design/human-interface-guidelines/icons
Skills: axiom-hig, axiom-liquid-glass, axiom-liquid-glass-ref, axiom-swiftui-layout-ref, axiom-accessibility-diag, axiom-tvos
Last Updated: Based on Apple HIG (2024-2025), WWDC25-356, WWDC19-808 Skill Type: Reference (Comprehensive guide with code examples)
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
Activates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.