capacitor-accessibility
SKILL.md
Accessibility in Capacitor Apps
Build inclusive apps that work for everyone.
When to Use This Skill
- User needs accessibility
- User wants screen reader support
- User asks about WCAG
- User needs focus management
Quick Checklist
- Semantic HTML
- Alt text for images
- Touch targets 44x44pt
- Color contrast 4.5:1
- Focus indicators
- Screen reader labels
- Keyboard navigation
Screen Reader Support
Labels and Hints
// Accessible button
<button
aria-label="Delete item"
aria-describedby="delete-hint"
>
<TrashIcon />
</button>
<span id="delete-hint" className="sr-only">
Permanently removes this item
</span>
// Accessible input
<label htmlFor="email">Email</label>
<input
id="email"
type="email"
aria-required="true"
aria-invalid={hasError}
aria-describedby={hasError ? "email-error" : undefined}
/>
{hasError && <span id="email-error">Invalid email</span>}
Live Regions
// Announce dynamic content
<div aria-live="polite" aria-atomic="true">
{message}
</div>
// Urgent announcements
<div aria-live="assertive" role="alert">
{error}
</div>
Touch Targets
/* Minimum 44x44pt */
button, a, input {
min-height: 44px;
min-width: 44px;
}
/* Icon buttons need padding */
.icon-button {
padding: 12px;
}
Color Contrast
/* Good contrast (4.5:1 for text) */
.text {
color: #333333;
background: #ffffff;
}
/* Don't rely on color alone */
.error {
color: #d32f2f;
border-left: 4px solid #d32f2f; /* Visual indicator */
}
.error::before {
content: "⚠ "; /* Icon indicator */
}
Focus Management
// Move focus after navigation
useEffect(() => {
const heading = document.querySelector('h1');
heading?.focus();
}, [page]);
// Trap focus in modals
function trapFocus(element: HTMLElement) {
const focusable = element.querySelectorAll(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const first = focusable[0] as HTMLElement;
const last = focusable[focusable.length - 1] as HTMLElement;
element.addEventListener('keydown', (e) => {
if (e.key === 'Tab') {
if (e.shiftKey && document.activeElement === first) {
e.preventDefault();
last.focus();
} else if (!e.shiftKey && document.activeElement === last) {
e.preventDefault();
first.focus();
}
}
});
}
Native Accessibility
iOS VoiceOver
// Custom accessibility in native code
element.isAccessibilityElement = true
element.accessibilityLabel = "Play video"
element.accessibilityHint = "Double tap to play"
element.accessibilityTraits = .button
Android TalkBack
// Custom accessibility
ViewCompat.setAccessibilityDelegate(view, object : AccessibilityDelegateCompat() {
override fun onInitializeAccessibilityNodeInfo(
host: View,
info: AccessibilityNodeInfoCompat
) {
super.onInitializeAccessibilityNodeInfo(host, info)
info.contentDescription = "Play video"
}
})
Testing
# iOS: Enable VoiceOver in Simulator
# Settings > Accessibility > VoiceOver
# Android: Enable TalkBack
# Settings > Accessibility > TalkBack
# Web: Use axe-core
bunx @axe-core/cli https://localhost:3000
Resources
- WCAG Guidelines: https://www.w3.org/WAI/WCAG21/quickref
- iOS Accessibility: https://developer.apple.com/accessibility
- Android Accessibility: https://developer.android.com/accessibility
Weekly Installs
34
Repository
cap-go/capacitor-skillsFirst Seen
Jan 25, 2026
Security Audits
Installed on
claude-code24
cursor16
opencode14
github-copilot14
gemini-cli13
codex13