All skills

Comprehensive iOS development guidance including Swift best practices, SwiftUI patterns, UI/UX review against HIG, and app planning. Use for iOS code review, best practices, accessibility audits, or planning new iOS apps.

  • 38 files
  • 438.7 KB
  • Updated 3 months ago
  • GitHub

Use this Skill: https://skilld.dev/gh/rshankras/claude-code-apple-skills/ios

This session only. Nothing lands on disk.

ui-reviewaccessibility-quick-ref.md

≈1.8k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Accessibility Quick Reference

Quick reference for SwiftUI accessibility implementation.

Essential Modifiers

Labels & Descriptions

// Label: What the element is
.accessibilityLabel("Add new expense")

// Value: Current state/value
.accessibilityValue("$150.00")

// Hint: What happens when activated
.accessibilityHint("Creates a new expense in this group")

Traits

// Add traits
.accessibilityAddTraits(.isButton)
.accessibilityAddTraits(.isHeader)
.accessibilityAddTraits(.isSelected)
.accessibilityAddTraits(.updatesFrequently)

// Remove traits
.accessibilityRemoveTraits(.isImage)

Grouping & Hiding

// Combine multiple elements into one
VStack {
    Text("Total")
    Text("$150")
}
.accessibilityElement(children: .combine)

// Hide decorative elements
Image("background-pattern")
    .accessibilityHidden(true)

Custom Actions

.accessibilityAction(named: "Delete") {
    deleteExpense()
}

.accessibilityAction(named: "Edit") {
    showEditSheet()
}

Common Patterns

Icon-Only Buttons

// ❌ Bad
Button {
    addExpense()
} label: {
    Image(systemName: "plus")
}

// ✅ Good
Button {
    addExpense()
} label: {
    Image(systemName: "plus")
}
.accessibilityLabel("Add expense")

Custom Controls

// ❌ Bad - VoiceOver doesn't know it's tappable
Image(systemName: "star")
    .onTapGesture { toggleFavorite() }

// ✅ Good
Image(systemName: "star")
    .onTapGesture { toggleFavorite() }
    .accessibilityAddTraits(.isButton)
    .accessibilityLabel("Favorite")
    .accessibilityValue(isFavorite ? "On" : "Off")

Lists with Actions

List {
    ForEach(expenses) { expense in
        ExpenseRow(expense: expense)
            .accessibilityAction(named: "Delete") {
                delete(expense)
            }
            .accessibilityAction(named: "Edit") {
                edit(expense)
            }
    }
}

Toggle States

Toggle("Enable notifications", isOn: $notificationsEnabled)
    .accessibilityValue(notificationsEnabled ? "Enabled" : "Disabled")

Progress & Status

ProgressView("Loading expenses", value: progress, total: 1.0)
    .accessibilityLabel("Loading")
    .accessibilityValue("\(Int(progress * 100)) percent complete")

Dynamic Type Support

Use Semantic Text Styles

// ✅ Good - Scales automatically
Text("Expense Title")
    .font(.headline)

Text("Description")
    .font(.body)

Text("Date")
    .font(.caption)

// ❌ Bad - Fixed size
Text("Expense Title")
    .font(.system(size: 18))

Custom Fonts with Scaling

// ✅ Good - Custom font that scales
Text("Title")
    .font(.custom("SF Pro Display", size: 17, relativeTo: .body))

// ❌ Bad - Fixed custom font
Text("Title")
    .font(.custom("SF Pro Display", fixedSize: 17))

Handle Large Text

// Use ViewThatFits for flexibility
ViewThatFits {
    HStack {
        Text("Long text here")
        Spacer()
        Text("$150")
    }

    VStack(alignment: .leading) {
        Text("Long text here")
        Text("$150")
    }
}

// Or use dynamic layout
@Environment(\.sizeCategory) var sizeCategory

var body: some View {
    if sizeCategory.isAccessibilityCategory {
        VStack { /* Vertical layout */ }
    } else {
        HStack { /* Horizontal layout */ }
    }
}

Size Model

  • 12 sizes total: 7 default + 5 accessibility sizes. .body runs 17pt at the default size, 28pt at the first accessibility size, 53pt at the largest — roughly 3× (WWDC24 10074).
  • The App Store Accessibility Nutrition Label claim bar is 200% text scaling; the maximum accessibility size is ~310% — see ios/accessibility-audit for the label evaluation workflow.

Large Content Viewer

Scaling is always preferred — use the viewer only for bars that legitimately can't grow: tab bars, nav bars, toolbars, custom fixed-height bars (WWDC19 261). Rationale: a tab bar takes under 10% of screen height; scaled to accessibility sizes it would eat almost a quarter (WWDC24 10074). At accessibility text sizes, long-pressing a bar item shows a large HUD of its glyph + title; lifting the finger activates it. System bars are automatic; custom bars adopt it:

// SwiftUI
FigureButton(figure: figure)
    .accessibilityShowsLargeContentViewer {
        Label(figure.title, systemImage: figure.systemImage)
    }

// UIKit — UILargeContentViewerItem properties + the interaction (WWDC19 261)
button.showsLargeContentViewer = true
button.largeContentTitle = "Favorites"
button.largeContentImage = UIImage(systemName: "star.fill")
button.scalesLargeContentImage = true      // needs Preserve Vector Data on the asset
customBar.addInteraction(UILargeContentViewerInteraction())
// ❌ Body content that could scale, "fixed" with the viewer instead
label.font = UIFont.systemFont(ofSize: 13)

// ✅ Scale what can scale; the viewer is only for bars that can't
label.font = UIFont.preferredFont(forTextStyle: .body)
label.adjustsFontForContentSizeCategory = true

Color & Contrast

Semantic Colors

// ✅ Good - Adapts to light/dark mode
Text("Title")
    .foregroundColor(.primary)

Background()
    .fill(Color(.systemBackground))

// ❌ Bad - Fixed colors
Text("Title")
    .foregroundColor(.black)

Background()
    .fill(Color.white)

Contrast Requirements

Use Xcode's Accessibility Inspector to verify contrast ratios for text and UI components.

Testing Checklist

VoiceOver Testing

  • All interactive elements have labels
  • Navigation order is logical
  • Custom actions work correctly
  • Dynamic content is announced

Dynamic Type Testing

  • Test at largest size (Accessibility XXXL)
  • No clipped text
  • Layouts adapt appropriately
  • Buttons remain tappable

Visual Testing

  • Test in Dark Mode
  • Test with Increased Contrast
  • Test with Reduce Transparency
  • Test with Reduce Motion

Keyboard Testing (iPad/Mac)

  • All actions have keyboard shortcuts
  • Focus indicator is visible
  • Tab order is logical

Testing in Simulator

Enable Accessibility Features

Settings → Accessibility → VoiceOver → On
Settings → Accessibility → Display & Text Size → Larger Text
Settings → Accessibility → Display & Text Size → Increase Contrast
Settings → Accessibility → Motion → Reduce Motion

Xcode Accessibility Inspector

Xcode → Open Developer Tool → Accessibility Inspector

Features:

  • Inspect element accessibility properties
  • Audit for common issues
  • Check color contrast
  • Test with different settings

Full audit workflow — automated performAccessibilityAudit XCUITests, Inspector triage, and Accessibility Nutrition Label evaluation — lives in ios/accessibility-audit.

Resources

Source: SKILL.md on GitHub

No third-party reports yet.

Signed by skilld at 32566aa. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 3 months ago
What it can do
Reads files Network
last_verified
2026-07-16
review_by
2027-06-22
os_version
iOS 27 / macOS 27
All 4 allowed tools
ReadGlobGrepWebFetch

README badge

README badge for rshankras/claude-code-apple-skills/ios