
Accessibility Patterns
- 21 installs
- 60 repo stars
- Updated June 14, 2026
- ahmed3elshaer/everything-claude-code-mobile
accessibility-patterns is a Claude Code skill providing mobile accessibility patterns for Android Jetpack Compose and iOS SwiftUI.
About
accessibility-patterns is a Claude Code skill that provides mobile accessibility code patterns for Android Jetpack Compose and iOS SwiftUI. It shows content descriptions, semantics modifiers, minimum 48dp touch targets, live regions, semantic grouping, roles, and traversal order on Android, and accessibility labels, hints, and child combining on iOS. Developers use it to make mobile UI screen-reader friendly and WCAG-aligned.
- Mobile accessibility patterns for Android Jetpack Compose and iOS SwiftUI
- Covers content descriptions, semantics, 48dp touch targets, and live regions
- Screen-reader grouping, roles, traversal order, and WCAG-aligned contrast
Accessibility Patterns by the numbers
- 21 all-time installs (skills.sh)
- Ranked #732 of 1,039 Mobile Development skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
accessibility-patterns capabilities & compatibility
- Capabilities
- mobile accessibility · compose ui · swiftui ui
- Use cases
- frontend · ui design
- Pricing
- Free
What accessibility-patterns says it does
Mobile accessibility patterns for Android and iOS - content descriptions, touch targets, screen reader support, WCAG compliance, dynamic type, and color contrast.
Material 3 enforces 48dp minimum automatically for clickable elements
npx skills add https://github.com/ahmed3elshaer/everything-claude-code-mobile --skill accessibility-patternsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 21 |
|---|---|
| repo stars | ★ 60 |
| Last updated | June 14, 2026 |
| Repository | ahmed3elshaer/everything-claude-code-mobile ↗ |
What it does
Add screen-reader support, correct touch targets, and semantic accessibility to Android Compose and iOS SwiftUI mobile UIs.
Who is it for?
Making Android Compose and iOS SwiftUI screens screen-reader friendly with correct semantics and touch targets.
Skip if: Web accessibility or non-mobile UI; it targets Compose and SwiftUI specifically.
When should I use this skill?
Adding content descriptions, screen-reader support, touch targets, or WCAG compliance to a mobile UI.
What you get
Accessible Compose and SwiftUI screens with labels, semantics, live regions, and WCAG-aligned targets.
- Accessible Compose and SwiftUI UI code
Files
Mobile Accessibility Patterns
Android / Jetpack Compose
Content Descriptions
// Images and icons must have content descriptions
Image(
painter = painterResource(R.drawable.profile_photo),
contentDescription = "User profile photo"
)
Icon(
imageVector = Icons.Default.Settings,
contentDescription = "Open settings"
)
// Decorative elements use null
Image(
painter = painterResource(R.drawable.decorative_divider),
contentDescription = null // purely decorative
)Semantics Modifier
// Custom semantic properties
Box(
modifier = Modifier.semantics {
contentDescription = "User card for Alice Johnson, 3 unread messages"
stateDescription = "Expanded"
}
)
// Heading hierarchy for screen reader navigation
Text(
text = "Account Settings",
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier.semantics { heading() }
)
// Live region for dynamic content updates
Text(
text = "Items in cart: $count",
modifier = Modifier.semantics {
liveRegion = LiveRegionMode.Polite
}
)
// Assertive live region for critical updates
Text(
text = errorMessage,
modifier = Modifier.semantics {
liveRegion = LiveRegionMode.Assertive
}
)Minimum Touch Target Size
// Material 3 enforces 48dp minimum automatically for clickable elements
// For custom elements, ensure minimum size:
IconButton(
onClick = { /* action */ },
modifier = Modifier.sizeIn(minWidth = 48.dp, minHeight = 48.dp)
) {
Icon(Icons.Default.Close, contentDescription = "Close dialog")
}
// Small icon with expanded touch target
Box(
modifier = Modifier
.size(48.dp)
.clickable(onClick = { /* action */ }),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Default.Info,
contentDescription = "More information",
modifier = Modifier.size(24.dp)
)
}Grouping and Merging Semantics
// Merge child semantics into a single announcement
Row(
modifier = Modifier
.clearAndSetSemantics {
contentDescription = "Alice Johnson, Software Engineer, Online"
}
.clickable { onUserClick() }
) {
Avatar(url = user.avatarUrl)
Column {
Text(user.name)
Text(user.title)
}
OnlineIndicator(isOnline = user.isOnline)
}
// Role assignment
Box(
modifier = Modifier
.clickable { onAction() }
.semantics { role = Role.Button }
) {
Text("Custom Button")
}
// Tab role
Text(
text = tabTitle,
modifier = Modifier
.clickable { onTabSelect() }
.semantics {
role = Role.Tab
selected = isSelected
}
)Toggle and Switch Accessibility
Row(
modifier = Modifier
.toggleable(
value = isEnabled,
onValueChange = { onToggle(it) },
role = Role.Switch
)
.padding(16.dp)
.semantics {
contentDescription = "Dark mode"
stateDescription = if (isEnabled) "Enabled" else "Disabled"
}
) {
Text("Dark Mode", modifier = Modifier.weight(1f))
Switch(checked = isEnabled, onCheckedChange = null) // null: Row handles toggle
}Traversal Order
Column(
modifier = Modifier.semantics {
traversalIndex = 0f // read first
}
) {
Text("Important announcement")
}
Column(
modifier = Modifier.semantics {
traversalIndex = 1f // read second
}
) {
Text("Secondary content")
}iOS / SwiftUI
Accessibility Labels and Hints
Image(systemName: "gear")
.accessibilityLabel("Settings")
.accessibilityHint("Opens application settings")
Button(action: { deleteItem() }) {
Image(systemName: "trash")
}
.accessibilityLabel("Delete item")
.accessibilityHint("Permanently removes this item from your list")Combining Child Elements
HStack {
Image(systemName: "person.circle")
VStack(alignment: .leading) {
Text(user.name)
Text(user.role)
}
}
.accessibilityElement(children: .combine) // reads as single element
// Ignore children, provide custom label
HStack {
StarRating(rating: 4.5)
}
.accessibilityElement(children: .ignore)
.accessibilityLabel("Rating: 4.5 out of 5 stars")Dynamic Type Support
// Use system text styles that scale automatically
Text("Heading")
.font(.title)
Text("Body text")
.font(.body)
// Custom sizes that scale
@ScaledMetric(relativeTo: .body) var iconSize: CGFloat = 24
Image(systemName: "star.fill")
.frame(width: iconSize, height: iconSize)
// Fixed minimum line height
Text("Important text")
.font(.body)
.lineSpacing(4)Reduce Motion Support
@Environment(\.accessibilityReduceMotion) var reduceMotion
var animation: Animation? {
reduceMotion ? nil : .spring(response: 0.5)
}
Button("Animate") {
withAnimation(animation) {
isExpanded.toggle()
}
}VoiceOver Rotor Support
List(items) { item in
ItemRow(item: item)
.accessibilityRotorEntry(id: item.id, in: .headings)
}
// Custom rotor
.accessibilityRotor("Unread Messages") {
ForEach(messages.filter(\.isUnread)) { message in
AccessibilityRotorEntry(message.subject, id: message.id)
}
}Accessibility Actions
ItemRow(item: item)
.accessibilityAction(named: "Delete") {
deleteItem(item)
}
.accessibilityAction(named: "Mark as favorite") {
toggleFavorite(item)
}Cross-Platform Patterns
Color Contrast Requirements (WCAG 2.1)
Minimum contrast ratios:
- Normal text: 4.5:1 (AA)
- Large text: 3.0:1 (AA, >=18sp or >=14sp bold)
- UI components: 3.0:1 (AA)
- Enhanced (AAA): 7.0:1 for normal text, 4.5:1 for large text
Common passing combinations:
- #000000 on #FFFFFF -> 21:1 (pass all)
- #595959 on #FFFFFF -> 7.0:1 (pass AAA)
- #767676 on #FFFFFF -> 4.54:1 (pass AA)
- #949494 on #FFFFFF -> 2.95:1 (FAIL AA)Focus Management
// Android/Compose: Request focus
val focusRequester = remember { FocusRequester() }
TextField(
value = text,
onValueChange = { text = it },
modifier = Modifier.focusRequester(focusRequester)
)
LaunchedEffect(Unit) {
focusRequester.requestFocus()
}// iOS/SwiftUI: Focus state
@FocusState private var isTextFieldFocused: Bool
TextField("Search", text: $query)
.focused($isTextFieldFocused)
Button("Focus Search") {
isTextFieldFocused = true
}Error Announcements
// Android: Announce error to screen reader
Text(
text = "Invalid email address",
color = MaterialTheme.colorScheme.error,
modifier = Modifier.semantics {
liveRegion = LiveRegionMode.Assertive
error("Invalid email address")
}
)// iOS: Post accessibility notification
AccessibilityNotification.Announcement("Invalid email address")
.post()Testing Accessibility
Android
@Test
fun profileCard_hasCorrectSemantics() {
composeTestRule.setContent {
ProfileCard(user = testUser)
}
composeTestRule
.onNodeWithContentDescription("User profile photo")
.assertExists()
composeTestRule
.onNode(hasClickAction() and hasText("View Profile"))
.assert(hasMinimumTouchTargetSize())
}Manual Testing Checklist
1. Enable TalkBack (Android) / VoiceOver (iOS)
2. Navigate through the entire screen using swipe gestures
3. Verify every interactive element is reachable and announced
4. Check that images have meaningful descriptions (or are hidden if decorative)
5. Verify touch targets are at least 48dp x 48dp
6. Test with font scaling at 200%
7. Test with display size set to largest
8. Test with high contrast / bold text enabled
9. Verify color is not the only indicator of state
10. Check focus order matches visual reading orderBest Practices
- Every interactive element must have a content description or accessible label.
- Never rely solely on color to convey meaning; pair with icons, text, or patterns.
- Group related elements so screen readers announce them as a single unit.
- Use heading semantics to create a navigable document structure.
- Test with real assistive technology, not just automated checks.
- Support both larger text sizes and reduced motion preferences.
- Provide live region announcements for dynamic content changes (toasts, counters, errors).
- Minimum 48dp (Android) / 44pt (iOS) touch target for all interactive elements.
Related skills
FAQ
Which platforms does accessibility-patterns cover?
Android with Jetpack Compose and iOS with SwiftUI.
What accessibility concerns does it address?
Content descriptions, semantics, minimum 48dp touch targets, live regions, roles, traversal order, and dynamic type.