Automated and manual accessibility auditing, WCAG compliance, and screen reader testing for mobile apps
Use this skill when the developer asks about:
| Input | Description |
|---|---|
| Framework | expo (React Native) or flutter |
| Scope | Full audit, specific screen, or CI setup |
Use mobile_auditAccessibility for a static analysis scan:
Use MCP tool: mobile_auditAccessibility
framework: "expo"
The tool scans source files for:
accessibilityLabel / Semantics on interactive elementsaccessibilityRole annotations// Bad
<TouchableOpacity onPress={onDelete}>
<Icon name="trash" />
</TouchableOpacity>
// Good
<TouchableOpacity
onPress={onDelete}
accessibilityLabel="Delete item"
accessibilityRole="button"
accessibilityHint="Removes this item from your list"
>
<Icon name="trash" />
</TouchableOpacity>
// Minimum 44x44pt
<Pressable
onPress={onPress}
style={{ minWidth: 44, minHeight: 44 }}
hitSlop={8}
>
<Icon name="settings" size={24} />
</Pressable>
import { PixelRatio } from "react-native";
const fontScale = PixelRatio.getFontScale();
// Ensure layouts don't break at 2x font scale
// Use maxFontSizeMultiplier on Text to cap if layout breaks
<Text maxFontSizeMultiplier={1.5}>Content</Text>
import { AccessibilityInfo } from "react-native";
const [reduceMotion, setReduceMotion] = useState(false);
useEffect(() => {
AccessibilityInfo.isReduceMotionEnabled().then(setReduceMotion);
const sub = AccessibilityInfo.addEventListener(
"reduceMotionChanged",
setReduceMotion
);
return () => sub.remove();
}, []);
import { AccessibilityInfo } from "react-native";
AccessibilityInfo.announceForAccessibility("Item deleted");
// Bad
GestureDetector(
onTap: onDelete,
child: Icon(Icons.delete),
)
// Good
Semantics(
label: 'Delete item',
button: true,
hint: 'Removes this item from your list',
child: GestureDetector(
onTap: onDelete,
child: const Icon(Icons.delete),
),
)
// Material guidelines: 48x48 logical pixels minimum
SizedBox(
width: 48,
height: 48,
child: IconButton(
onPressed: onSettings,
icon: const Icon(Icons.settings),
),
)
MediaQuery(
data: MediaQuery.of(context).copyWith(textScaler: TextScaler.linear(2.0)),
child: child,
)
final disableAnimations = MediaQuery.of(context).disableAnimations;
SemanticsService.announce('Item deleted', TextDirection.ltr);
| Test | Pass Criteria |
|---|---|
| All buttons announced | Label read aloud, role stated |
| Images described | Alt text read or skipped if decorative |
| Touch targets | ≥ 44pt (iOS) / ≥ 48dp (Android) |
| Contrast ratio | ≥ 4.5:1 normal text, ≥ 3:1 large text |
| Font scaling | Layout intact at 200% font size |
| Focus order | Logical top-to-bottom, left-to-right |
| Reduced motion | Animations skipped when enabled |
import { render } from "@testing-library/react-native";
test("delete button has accessibility label", () => {
const { getByRole } = render(<DeleteButton />);
const btn = getByRole("button", { name: "Delete item" });
expect(btn).toBeTruthy();
});
testWidgets('delete button has semantics', (tester) async {
await tester.pumpWidget(const MaterialApp(home: DeleteButton()));
expect(
find.bySemanticsLabel('Delete item'),
findsOneWidget,
);
});
| Resource | URL |
|---|---|
| WCAG 2.1 (W3C) | https://www.w3.org/TR/WCAG21/ |
| RN Accessibility | https://reactnative.dev/docs/accessibility |
| Flutter Accessibility | https://docs.flutter.dev/accessibility-and-internationalization/accessibility |
| axe DevTools Mobile | https://www.deque.com/axe/devtools/mobile/ |
| iOS HIG Accessibility | https://developer.apple.com/design/human-interface-guidelines/accessibility |
User: "Run an accessibility audit on my app and fix any violations"
Assistant:
mobile_auditAccessibility to scan all source filesaccessibilityLabel and accessibilityRole to interactive elementsmobile_generateTestFile to prevent regressions| Tool | When |
|---|---|
mobile_auditAccessibility | Run automated a11y scan on the project |
mobile_generateTestFile | Generate a11y-focused test file |
accessible={false} (RN) or excludeFromSemantics: true (Flutter).mobile-theming - semantic color tokens for consistent contrastmobile-component-patterns - accessible component architecturemobile-forms-validation - accessible form error handling