From ios-frameworks
Audit Apple platform UI code for accessibility — VoiceOver, Dynamic Type, keyboard navigation, colour contrast, and semantic correctness — with prioritised, patch-ready fixes
How this skill is triggered — by the user, by Claude, or both
Slash command
/ios-frameworks:beepus-maximus-ios-accessibilityThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Platforms:** iOS, iPadOS, macOS
Platforms: iOS, iPadOS, macOS Frameworks: SwiftUI, UIKit, AppKit Category: Accessibility Output style: Prioritised findings (P0/P1/P2) + patch-ready code + manual testing checklist
Owns:
Does NOT own:
Reason about semantics first. Understand what a control means before deciding what modifiers it needs. A button that already has visible text does not need a redundant accessibilityLabel. A decorative image should be hidden, not labelled.
Use the right platform auditor. SwiftUI, UIKit, and AppKit have different APIs and different conventions. Never suggest UIKit APIs in SwiftUI code or vice versa. Consult the platform-specific reference file.
Prioritise findings as P0 / P1 / P2.
Provide patch-ready suggestions. Every finding must include a concrete code fix that can be applied directly. Prefer minimal diffs. Specify where the code belongs (e.g., viewDidLoad, modifier chain, init).
Accessibility is not a checklist. Do not mechanically apply modifiers. Every change must have a clear justification rooted in how an assistive technology user would experience the interface.
Respect constraints. Do not rewrite architecture, change user-facing copy, or break layout unless it is the only way to resolve an accessibility blocker. Prefer minimal, localised, safe changes.
Cross-platform when possible. When auditing SwiftUI code that runs on both iOS and macOS, flag platform-specific concerns (e.g., touch targets on iOS, key view loop on macOS) and keep fixes portable where feasible.
Assistive Access is a separate scene, not a toggle. If the app serves users with cognitive disabilities, provide an AssistiveAccess { } scene with a flat, simplified UI. See references/assistive-access.md.
Accessibility is not a retrofit. Every UI element must include accessibility code in its first draft. Use this table when writing new code.
| UI Pattern | Required Accessibility Code | Example |
|---|---|---|
| Icon-only button | .accessibilityLabel("descriptive action") | Button { } label: { Image(systemName: "trash") }.accessibilityLabel("Delete item") |
| Decorative image | .accessibilityHidden(true) | Image("background-pattern").accessibilityHidden(true) |
| Informational image | .accessibilityLabel("description") | Image("chart-trend-up").accessibilityLabel("Trending upward this week") |
| Custom toggle/switch | .accessibilityAddTraits(.isToggle) + .accessibilityValue(isOn ? "On" : "Off") | — |
| Custom slider/stepper | .accessibilityValue + .accessibilityAdjustableAction | Provide increment/decrement actions |
| Grouped content (card) | .accessibilityElement(children: .combine) or manual label | Combine card title + subtitle + value into one VoiceOver stop |
onTapGesture on non-Button | Wrap in Button instead, or add .accessibilityAddTraits(.isButton) | Prefer Button — it gets keyboard and switch control for free |
withAnimation / motion | Provide @Environment(\.accessibilityReduceMotion) alternative | Crossfade instead of slide, or skip animation entirely |
| Custom progress indicator | .accessibilityValue("\(Int(progress * 100)) percent") | Keep value updated as progress changes |
| Tab-like custom control | .accessibilityAddTraits(.isTabBar) on container | Each tab gets .accessibilityAddTraits(.isSelected) when active |
| Drag-and-drop reorderable list | .accessibilityAction(.move) or accessibility rotor | Provide non-gesture reorder mechanism |
| Time-sensitive content (toast/snackbar) | .accessibilityLiveRegion(.polite) or post announcement | AccessibilityNotification.Announcement("Item saved").post() |
// TODO: [VERIFY] CommentsWhen an accessibility label is inferred rather than explicitly confirmed (e.g., derived from an SF Symbol name, a variable name, or surrounding context), tag it with // TODO: [VERIFY]:
Image(systemName: "heart.fill")
.accessibilityLabel("Favorites") // TODO: [VERIFY] — inferred from symbol name, confirm with design
SF Symbol names rarely match user intent. "heart.fill" might mean "Favorites", "Liked", "Health", or "Save". The // TODO: [VERIFY] comment ensures a human confirms the label before shipping.
Rule: Every inferred accessibility label gets // TODO: [VERIFY]. Every explicitly provided label (from a spec, design, or user instruction) does not.
Identify the framework. Determine whether the code is SwiftUI, UIKit, or AppKit, then consult the corresponding reference file.
Read the UI semantically. Before scanning for missing modifiers, understand the screen's purpose, the user's primary task, and the intended interaction model.
Audit against the platform checklist. Walk through the relevant reference file's checklist areas: VoiceOver semantics, Dynamic Type, keyboard/focus, colour/contrast, touch targets, motion, and announcements.
Classify findings. Assign P0/P1/P2 to each issue. Group by priority in the output.
Write patch-ready fixes. For each finding, provide a minimal before/after diff or code snippet. Never invent APIs that do not exist.
Append a manual testing checklist. Provide 4-8 concrete verification steps the developer can perform with VoiceOver, Dynamic Type settings, and keyboard navigation.
### Findings
- **P0:** [description] — [why it matters]
- **P1:** [description] — [why it matters]
- **P2:** [description] — [why it matters]
### Suggested Patch
\```diff
- old code
+ new code
\```
### Manual Testing Checklist
- [ ] VoiceOver: ...
- [ ] Dynamic Type: ...
- [ ] Keyboard: ...
- [ ] Colour/contrast: ...
Platform-specific audit rules and patterns:
SwiftUI Audit Reference — SwiftUI accessibility patterns, VoiceOver, Dynamic Type, common mistakes
UIKit Audit Reference — UIAccessibility API, trait collections, custom controls, Dynamic Type
AppKit Audit Reference — NSAccessibility, keyboard navigation, tables/outline views, macOS concerns
Manual Testing Guide — VoiceOver testing workflow, Dynamic Type testing, Reduce Motion verification
Assistive Access Reference — AssistiveAccess scene, runtime detection, design guidelines
When preparing an app for submission, generate Accessibility Nutrition Label claims for App Store Connect. The 9 categories are:
For each category, verify with a concrete test (e.g., "Navigate the entire main flow with VoiceOver — every screen reachable, every action performable"). Only claim categories that pass verification.
See also: shipping for the full App Store submission checklist.
External references:
npx claudepluginhub 4eleven7/claude-skills --plugin ios-frameworksCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.