Help us improve
Share bugs, ideas, or general feedback.
Scan SwiftUI views and add missing accessibility identifiers using a consistent {screen}-{type}-{name} naming convention. Also flags Dynamic Type compatibility issues. Use when you need to add accessibility support, make views testable, add VoiceOver labels, or prepare for UI testing.
npx claudepluginhub yusufkaran/swiftui-autotest-skill --plugin swiftui-autotest-skillHow this skill is triggered — by the user, by Claude, or both
Slash command
/swiftui-autotest-skill:add-accessibilityThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Use this skill to scan all SwiftUI files in a project, find interactive elements missing accessibility identifiers, and add them using a consistent `{screen}-{type}-{name}` naming convention. Also flags Dynamic Type compatibility issues without auto-fixing them.
Applies platform accessibility best practices to SwiftUI, UIKit, and AppKit code, covering VoiceOver, Dynamic Type, Reduce Motion, and all Nutrition Label categories. Ensures a11y from first draft in UI writing, editing, or review.
Reviews SwiftUI code for view composition, state management (@State, @Binding, @Observable), performance, and accessibility. Use for .swift files with SwiftUI views or UI code.
Reviews SwiftUI and Swift code for modern APIs, best practices, performance, accessibility, data flow, navigation, and Clean Architecture.
Share bugs, ideas, or general feedback.
Use this skill to scan all SwiftUI files in a project, find interactive elements missing accessibility identifiers, and add them using a consistent {screen}-{type}-{name} naming convention. Also flags Dynamic Type compatibility issues without auto-fixing them.
--dry-run: Don't modify files, only report what would be changed--path=<path>: Scan only the specified directory (default: all SwiftUI files)--verbose: Log each identifier added in detailFind all *.swift files in the project
Filter to files containing SwiftUI views (struct X: View, #Preview, etc.)
In each file, detect these interactive elements:
Button — buttonsTextField and SecureField — input fieldsImage — imagesToggle — toggle switchesSlider — slidersPicker — pickersDatePicker — date pickersNavigationLink — navigation linksTabView tab items.onTapGesture views — tap gesture elementsLink — external linksFor each element, check existing accessibility state:
.accessibilityIdentifier()? → SKIP.accessibilityLabel()? → SKIPNaming convention: {screen}-{type}-{name}
Screen name: derived from the filename
LoginView.swift → loginOnboardingStepView.swift → onboarding-stepHomeTabView.swift → home-tabView suffix, convert camelCase to kebab-caseType: based on the element type
| SwiftUI Element | Type |
|---|---|
| Button | button |
| TextField | textfield |
| SecureField | securefield |
| Image | image |
| Toggle | toggle |
| Slider | slider |
| Picker | picker |
| DatePicker | datepicker |
| NavigationLink | navlink |
| Link | link |
| .onTapGesture view | tap |
| TabView item | tab |
Name: derived from the element's content
Button("Continue") → continueTextField("Email", ...) → emailImage(systemName: "gear") → gearImage("hero-banner") → hero-bannerToggle("Notifications", ...) → notificationsbutton-1, button-2)Example results:
login-button-continue
login-textfield-email
login-securefield-password
onboarding-image-hero-banner
settings-toggle-notifications
home-tab-profile
Add .accessibilityIdentifier("generated-id") to each element missing one:
// BEFORE
Button("Continue") {
viewModel.proceed()
}
// AFTER
Button("Continue") {
viewModel.proceed()
}
.accessibilityIdentifier("login-button-continue")
For Images, also add accessibilityLabel (for VoiceOver):
// BEFORE
Image(systemName: "gear")
// AFTER
Image(systemName: "gear")
.accessibilityIdentifier("settings-image-gear")
.accessibilityLabel("Settings")
For onTapGesture views, mark as accessibility elements:
// BEFORE
HStack {
Image("avatar")
Text(user.name)
}
.onTapGesture { showProfile() }
// AFTER
HStack {
Image("avatar")
Text(user.name)
}
.onTapGesture { showProfile() }
.accessibilityElement(children: .combine)
.accessibilityIdentifier("profile-tap-user-row")
.accessibilityAddTraits(.isButton)
Check Text elements for Dynamic Type compatibility:
Flag (report as warnings, do NOT auto-fix):
Text without .lineLimit() when the content could be longText without .minimumScaleFactor() in constrained areas.font(.system(size: XX)) with hardcoded font sizes instead of dynamic fonts like .font(.title), .font(.body)Report format:
⚠️ Dynamic Type Warnings:
LoginView.swift:42 - Text("Welcome back...") → missing lineLimit or minimumScaleFactor
LoginView.swift:58 - Text(...).font(.system(size: 14)) → consider using dynamic font (.body, .caption, etc.)
SettingsView.swift:23 - Text(longString) → missing lineLimit, risk of overflow with large text
Show a summary when the scan is complete:
✅ Accessibility Scan Complete
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Files scanned: 24
Elements found: 87
Already present: 31 (skipped)
Newly added: 56
- Button: 18
- TextField: 8
- Image: 12
- Toggle: 6
- Other: 12
⚠️ Dynamic Type Warnings: 7
(details above)
Pattern: {screen}-{type}-{name}
.accessibilityIdentifier(), .accessibilityLabel(), .accessibilityElement(), .accessibilityAddTraits()#if DEBUG — identifiers must be in production too (for real accessibility / VoiceOver){screen}-{type}-{index} format and flag it in verbose mode--dry-run mode, do not modify any files — only show the plan