Use when fixing VoiceOver issues, Dynamic Type violations, color contrast failures, touch target problems, keyboard navigation gaps, or Reduce Motion support - comprehensive accessibility diagnostics with WCAG compliance, Accessibility Inspector workflows, and App Store Review preparation for iOS/macOS
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Use when fixing VoiceOver issues, Dynamic Type violations, color contrast failures, touch target problems, keyboard navigation gaps, or Reduce Motion support - comprehensive accessibility diagnostics with WCAG compliance, Accessibility Inspector workflows, and App Store Review preparation for iOS/macOS
license
MIT
metadata
{"version":"1.0.0"}
Accessibility Diagnostics
Overview
Systematic accessibility diagnosis and remediation for iOS/macOS apps. Covers the 7 most common accessibility issues that cause App Store rejections and user complaints.
Core principle Accessibility is not optional. iOS apps must support VoiceOver, Dynamic Type, and sufficient color contrast to pass App Store Review. Users with disabilities depend on these features.
When to Use This Skill
Fixing VoiceOver navigation issues (missing labels, wrong element order)
Supporting Dynamic Type (text scaling for vision disabilities)
Meeting color contrast requirements (WCAG AA/AAA)
Fixing touch target size violations (< 44x44pt)
Adding keyboard navigation (iPadOS/macOS)
Supporting Reduce Motion (vestibular disorders)
Preparing for App Store Review accessibility requirements
Responding to user complaints about accessibility
The 7 Critical Accessibility Issues
1. VoiceOver Labels & Hints (CRITICAL - App Store Rejection)
Problem Missing or generic accessibility labels prevent VoiceOver users from understanding UI purpose.
WCAG 4.1.2 Name, Role, Value (Level A)
Common violations
// ❌ WRONG - No label (VoiceOver says "Button")Button(action: addToCart) {
Image(systemName: "cart.badge.plus")
}
// ❌ WRONG - Generic label
.accessibilityLabel("Button")
// ❌ WRONG - Reads implementation details
.accessibilityLabel("cart.badge.plus") // VoiceOver: "cart dot badge dot plus"// ✅ CORRECT - Descriptive labelButton(action: addToCart) {
Image(systemName: "cart.badge.plus")
}
.accessibilityLabel("Add to cart")
// ✅ CORRECT - With hint for complex actions
.accessibilityLabel("Add to cart")
.accessibilityHint("Double-tap to add this item to your shopping cart")
When to use hints
Action is not obvious from label ("Add to cart" is obvious, no hint needed)
Multi-step interaction ("Swipe right to confirm, left to cancel")
State change ("Double-tap to toggle notifications on or off")
Decorative elements
// ✅ CORRECT - Hide decorative images from VoiceOverImage("decorative-pattern")
.accessibilityHidden(true)
// ✅ CORRECT - Combine multiple elements into one labelHStack {
Image(systemName: "star.fill")
Text("4.5")
Text("(234 reviews)")
}
.accessibilityElement(children: .combine)
.accessibilityLabel("Rating: 4.5 stars from 234 reviews")
Testing
Enable VoiceOver: Cmd+F5 (simulator) or triple-click side button (device)
Navigate: Swipe right/left to move between elements
Listen: Does VoiceOver announce purpose clearly?
Check order: Does navigation order match visual layout?
2. Dynamic Type Support (HIGH - User Experience)
Problem Fixed font sizes prevent users with vision disabilities from reading text.
WCAG 1.4.4 Resize Text (Level AA - support 200% scaling without loss of content/functionality)
Simulator: Settings → Accessibility → Display & Text Size → Larger Text → Drag to maximum
Device: Settings → Accessibility → Display & Text Size → Larger Text
Check: Does text remain readable? Does layout adapt? Is any text clipped?
3. Color Contrast (HIGH - Vision Disabilities)
Problem Low contrast text is unreadable for users with vision disabilities or in bright sunlight.
WCAG
1.4.3 Contrast (Minimum) — Level AA
Normal text (< 18pt): 4.5:1 contrast ratio
Large text (≥ 18pt or ≥ 14pt bold): 3:1 contrast ratio
1.4.6 Contrast (Enhanced) — Level AAA
Normal text: 7:1 contrast ratio
Large text: 4.5:1 contrast ratio
Common violations
// ❌ WRONG - Low contrast (1.8:1 - fails WCAG)Text("Warning")
.foregroundColor(.yellow) // on white background// ❌ WRONG - Low contrast in dark modeText("Info")
.foregroundColor(.gray) // on black background// ✅ CORRECT - High contrast (7:1+ passes AAA)Text("Warning")
.foregroundColor(.orange) // or .red// ✅ CORRECT - System colors adapt to light/dark modeText("Info")
.foregroundColor(.primary) // Black in light mode, white in darkText("Secondary")
.foregroundColor(.secondary) // Automatic high contrast
Differentiate Without Color
// ❌ WRONG - Color alone indicates statusCircle()
.fill(isAvailable ? .green : .red)
// ✅ CORRECT - Color + icon/textHStack {
Image(systemName: isAvailable ?"checkmark.circle.fill" : "xmark.circle.fill")
Text(isAvailable ?"Available" : "Unavailable")
}
.foregroundColor(isAvailable ? .green : .red)
// ✅ CORRECT - Respect system preferenceifUIAccessibility.shouldDifferentiateWithoutColor {
// Use patterns, icons, or text instead of color alone
}
Testing
Use Color Contrast Analyzer tool (free download)
Screenshot your UI, measure text vs background
Check both light and dark mode
Settings → Accessibility → Display & Text Size → Increase Contrast (test with this ON)
Quick reference
Black (#000000) on White (#FFFFFF): 21:1 ✅ AAA
Dark Gray (#595959) on White: 7:1 ✅ AAA
Medium Gray (#767676) on White: 4.5:1 ✅ AA
Light Gray (#959595) on White: 2.8:1 ❌ Fails
4. Touch Target Sizes (MEDIUM - Motor Disabilities)
Problem Small tap targets are difficult or impossible for users with motor disabilities.
Video autoplay should also respect this preference
7. Common Violations (HIGH - App Store Review)
Images Without Labels
// ❌ WRONG - Informative image without labelImage("product-photo")
// ✅ CORRECT - Informative image with labelImage("product-photo")
.accessibilityLabel("Red sneakers with white laces")
// ✅ CORRECT - Decorative image hiddenImage("background-pattern")
.accessibilityHidden(true)
Buttons With Wrong Traits
// ❌ WRONG - Custom button without button traitText("Submit")
.onTapGesture {
submit()
}
// VoiceOver announces as "Submit, text" not "Submit, button"// ✅ CORRECT - Use Button for button-like controlsButton("Submit") {
submit()
}
// VoiceOver announces as "Submit, button"// ✅ CORRECT - Custom control with correct traitText("Submit")
.accessibilityAddTraits(.isButton)
.onTapGesture {
submit()
}
Inaccessible Custom Controls
// ❌ WRONG - Custom slider without accessibility supportstructCustomSlider: View {
@Bindingvar value: Doublevar body: someView {
// Drag gesture only, no VoiceOver supportGeometryReader { geo in// ...
}
.gesture(DragGesture()...)
}
}
// ✅ CORRECT - Custom slider with accessibility actionsstructCustomSlider: View {
@Bindingvar value: Doublevar body: someView {
GeometryReader { geo in// ...
}
.gesture(DragGesture()...)
.accessibilityElement()
.accessibilityLabel("Volume")
.accessibilityValue("\(Int(value))%")
.accessibilityAdjustableAction { direction inswitch direction {
case .increment:
value =min(value +10, 100)
case .decrement:
value =max(value -10, 0)
@unknowndefault:
break
}
}
}
}
Missing State Announcements
// ❌ WRONG - State change without announcementButton("Toggle") {
isOn.toggle()
}
// ✅ CORRECT - State change with announcementButton("Toggle") {
isOn.toggle()
UIAccessibility.post(
notification: .announcement,
argument: isOn ?"Enabled" : "Disabled"
)
}
// ✅ CORRECT - Automatic state with accessibilityValueButton("Toggle") {
isOn.toggle()
}
.accessibilityValue(isOn ?"Enabled" : "Disabled")
8. Assistive Access Support (iOS 17+ — Cognitive Disabilities)
Problem App is unavailable or broken in Assistive Access mode, excluding users with cognitive disabilities who rely on a simplified system experience.
Assistive Access is a system-wide mode (Settings > Accessibility > Assistive Access) that replaces the standard iOS UI with large controls, simplified navigation, and reduced cognitive load. Apps that don't opt in are hidden from users in this mode.
Symptom: App missing from Assistive Access home screen
Your app doesn't appear under "Optimized Apps" in Assistive Access settings.
<!-- ✅ FIX - Add to Info.plist --><key>UISupportsAssistiveAccess</key><true/>
This makes the app available and launches it full screen in Assistive Access mode. Without this key, users in Assistive Access mode cannot access your app at all.
Symptom: Standard UI too complex for Assistive Access users
Your app launches in Assistive Access but shows the full standard interface, overwhelming users who need simplified controls.
// ✅ FIX - Provide a dedicated Assistive Access scene@mainstructMyApp: App {
var body: someScene {
WindowGroup {
ContentView() // Standard UI
}
AssistiveAccess {
AssistiveAccessContentView() // Simplified UI
}
}
}
The AssistiveAccess scene type provides a separate entry point. When the system is in Assistive Access mode, it uses this scene instead of the standard WindowGroup. Native SwiftUI controls inside this scene automatically adopt the Assistive Access visual style (large buttons, prominent navigation, grid/row layout).
Symptom: App already designed for cognitive accessibility but displays in reduced frame
If your app is already purpose-built for users with cognitive disabilities (e.g., AAC apps), it may appear in a reduced frame rather than full screen.
<!-- ✅ FIX - Add to Info.plist for apps already designed for cognitive accessibility --><key>UISupportsFullScreenInAssistiveAccess</key><true/>
This displays your app identically to its standard appearance, bypassing the Assistive Access frame.
Detecting Assistive Access at runtime
structMyView: View {
@Environment(\.accessibilityAssistiveAccessEnabled) var assistiveAccessEnabled
var body: someView {
if assistiveAccessEnabled {
// Simplified content
} else {
// Standard content
}
}
}
UIKit implementation
For UIKit apps, use the .windowAssistiveAccessApplication scene session role in your UISceneConfiguration to route to a dedicated scene delegate for the Assistive Access experience.
Design principles for Assistive Access scenes
Distill to core functionality — One or two essential features, not the full app
Large, prominent controls — Ample spacing, no hidden gestures or timed interactions
Multiple representations — Pair text with icons; use visual alternatives
Step-by-step navigation — Clear back buttons, consistent patterns
Under design review pressure, you'll face requests to:
"Those VoiceOver labels make the code messy - can we skip them?"
"Dynamic Type breaks our carefully designed layout - let's lock font sizes"
"The high contrast requirement ruins our brand aesthetic"
"44pt touch targets are too big - make them smaller for a cleaner look"
These sound like reasonable design preferences. But they violate App Store requirements and exclude 15% of users. Your job: defend using App Store guidelines and legal requirements, not opinion.
Red Flags — Designer Requests That Violate Accessibility
If you hear ANY of these, STOP and reference this skill:
❌ "Skip VoiceOver labels on icon-only buttons" – App Store rejection (Guideline 2.5.1)
❌ "Use fixed 14pt font for compact design" – Excludes users with vision disabilities
❌ "3:1 contrast ratio is fine" – Fails WCAG AA for text (needs 4.5:1)
❌ "Disable Dynamic Type in this screen" – App Store rejection risk
❌ "Color-code without labels (red=error, green=success)" – Excludes colorblind users (8% of men)
How to Push Back Professionally
Step 1: Show the Guideline
"I want to support this design direction, but let me show you Apple's App Store
Review Guideline 2.5.1:
'Apps should support accessibility features such as VoiceOver and Dynamic Type.
Failure to include sufficient accessibility features may result in rejection.'
Here's what we need for approval:
1. VoiceOver labels on all interactive elements
2. Dynamic Type support (can't lock font sizes)
3. 4.5:1 contrast ratio for text, 3:1 for UI
4. 44x44pt minimum touch targets
Let me show where our design currently falls short..."
Step 2: Demonstrate the Risk
Open the app with accessibility features enabled:
VoiceOver (Cmd+F5): Show buttons announcing "Button" instead of purpose
Largest Text Size: Show layout breaking or text clipping
Color Contrast Analyzer: Show failing contrast ratios
Touch target overlay: Show targets < 44pt
Reference
App Store Review Guideline 2.5.1
WCAG 2.1 Level AA (industry standard)
ADA compliance requirements (legal risk in US)
Step 3: Offer Compromise
"I can achieve your aesthetic goals while meeting accessibility requirements:
1. VoiceOver labels: Add them programmatically (invisible in UI, required for approval)
2. Dynamic Type: Use layout techniques that adapt (examples from Apple HIG)
3. Contrast: Adjust colors slightly to meet 4.5:1 (I'll show options that preserve brand)
4. Touch targets: Expand hit areas programmatically (visual size stays the same)
These changes won't affect the visual design you're seeing, but they're required
for App Store approval and legal compliance."
Step 4: Document the Decision
If overruled (designer insists on violations):
Slack message to PM + designer:
"Design review decided to proceed with:
- Fixed font sizes (disabling Dynamic Type)
- 38x38pt buttons (below 44pt requirement)
- 3.8:1 text contrast (below 4.5:1 requirement)
Important: These changes violate App Store Review Guideline 2.5.1 and WCAG AA.
This creates three risks:
1. App Store rejection during review (adds 1-2 week delay)
2. ADA compliance issues if user files complaint (legal risk)
3. 15% of potential users unable to use app effectively
I'm flagging this proactively so we can prepare a response plan if rejected."
Why this works
You're not questioning their design taste
You're raising App Store rejection risk (business impact)
You're citing specific guidelines (not opinion)
You're offering solutions that preserve visual design
You're documenting the decision (protects you post-rejection)
Real-World Example: App Store Rejection (48-Hour Resubmit Window)
Scenario
48 hours until resubmit deadline after rejection
Apple cited: "2.5.1 - Insufficient VoiceOver support"
Designer says: "Just add generic labels quickly"
PM watching the meeting, wants fastest fix
What to do
// ❌ WRONG - Generic labels (will fail re-review)Button(action: addToCart) {
Image(systemName: "cart.badge.plus")
}
.accessibilityLabel("Button") // Apple will reject again// ✅ CORRECT - Descriptive labels (passes review)Button(action: addToCart) {
Image(systemName: "cart.badge.plus")
}
.accessibilityLabel("Add to cart")
.accessibilityHint("Double-tap to add this item to your shopping cart")
In the meeting, demonstrate
Enable VoiceOver (Cmd+F5)
Show "Button" announcement (generic - fails)
Show "Add to cart" announcement (descriptive - passes)
Reference Apple's rejection message: "Elements must have descriptive labels"
Time estimate 2-4 hours to audit all interactive elements and add proper labels.
Result
Honest time estimate prevents second rejection
Proper labels pass Apple review
Resubmit accepted within 48 hours
When to Accept the Design Decision (Even If You Disagree)
Sometimes designers have valid reasons to override accessibility guidelines. Accept if:
They understand the App Store rejection risk
They're willing to delay launch if rejected
You document the decision in writing
They commit to fixing if rejected
Document in Slack
"Design review decided to proceed with [specific violations].
We understand this creates:
- App Store rejection risk (Guideline 2.5.1)
- Potential 1-2 week delay if rejected
- Need to audit and fix all instances if rejected
Monitoring plan:
- Submit for review with current design
- If rejected, implement proper accessibility (estimated 2-4 hours)
- Have accessibility-compliant version ready as backup"
This protects both of you and shows you're not blocking - just de-risking.
WCAG Compliance Levels
Level A (Minimum — Required for App Store)
1.1.1 Non-text Content — Images have text alternatives
2.1.1 Keyboard — All functionality via keyboard (iPadOS/macOS)
4.1.2 Name, Role, Value — Elements have accessible names
Level AA (Standard — Recommended)
1.4.3 Contrast (Minimum) — 4.5:1 text, 3:1 UI
1.4.4 Resize Text — Support 200% text scaling
1.4.5 Images of Text — Use real text when possible
Level AAA (Enhanced — Best Practice)
1.4.6 Contrast (Enhanced) — 7:1 text, 4.5:1 UI
2.3.3 Animation from Interactions — Reduce Motion support
2.5.5 Target Size - 44x44pt minimum targets
Goal Meet Level AA for all content, Level AAA where feasible.
Quick Command Reference
After making fixes:
# Quick scan for new issues
/axiom:audit-accessibility
# Deep diagnosis for specific issues
/skill axiom:accessibility-diag
Remember Accessibility is not a feature, it's a requirement. 15% of users have some form of disability. Making your app accessible isn't just the right thing to do - it expands your user base and improves the experience for everyone.