Accessibility Guide - WCAG 2.1 Level AA Compliance
Overview
KoproGo is committed to providing an accessible platform that meets WCAG 2.1 Level AA standards. This document outlines our accessibility features, best practices, and testing guidelines.
✅ Implemented Features
2. Screen Reader Support
ARIA Landmarks: Proper
roleattributes (banner,main,contentinfo,navigation)ARIA Labels: All buttons and interactive elements have descriptive labels
Live Regions: Screen reader announcements for dynamic content updates
Semantic HTML: Proper use of headings, lists, buttons, and form elements
3. Color Contrast
All text meets WCAG AA contrast ratios:
Normal Text: 4.5:1 minimum contrast ratio
Large Text (18pt+ or 14pt+ bold): 3.1 minimum contrast ratio
Interactive Elements: 3:1 contrast ratio for focus indicators
4. Visual Design
Focus Visible: Clear focus indicators (
:focus-visiblepseudo-class)No Color-Only Information: Information never conveyed by color alone
Resizable Text: Text can be resized up to 200% without loss of functionality
Responsive Design: Works on all screen sizes and orientations
🛠️ Accessibility Components
AccessibleModal
Modal dialog with focus trap and keyboard navigation:
<AccessibleModal
isOpen={showModal}
title="Edit Expense"
description="Update expense details"
onClose={handleClose}
size="md"
>
<form>...</form>
<svelte:fragment slot="footer">
<AccessibleButton on:click={handleSave}>Save</AccessibleButton>
<AccessibleButton variant="secondary" on:click={handleClose}>Cancel</AccessibleButton>
</svelte:fragment>
</AccessibleModal>
Features:
Automatic focus trap
Escape key to close
Click outside to close
Screen reader announcements
Saves and restores previous focus
📚 Accessibility Utilities
Focus Management
import { trapFocus, FocusManager } from '../lib/accessibility';
// Trap focus within a container
const cleanup = trapFocus(containerElement);
// Save and restore focus
const manager = new FocusManager();
manager.save();
// ... do something ...
manager.restore();
Screen Reader Announcements
import { announce } from '../lib/accessibility';
// Polite announcement (doesn't interrupt)
announce('Changes saved successfully', 'polite');
// Assertive announcement (interrupts current reading)
announce('Error: Form validation failed', 'assertive');
Color Contrast Checking
import { meetsContrastRatio } from '../lib/accessibility';
const isAccessible = meetsContrastRatio('#10b981', '#ffffff', false);
// Returns true if contrast ratio meets WCAG AA standards
🧪 Testing
Automated Testing (axe-core)
Run automated accessibility tests:
npm run test:a11y
Manual Testing Checklist
Keyboard Navigation
Can access all interactive elements with Tab
Can activate buttons with Enter/Space
Can navigate lists with Arrow keys
Can close modals with Escape
Focus indicators visible on all elements
Screen Reader Testing
Test with NVDA (Windows)
Test with VoiceOver (macOS/iOS)
All images have alt text
Forms have proper labels
Dynamic content announces changes
Visual Testing
Check color contrast with browser DevTools
Test with 200% text zoom
Test in high contrast mode
Verify no information by color alone
📋 WCAG 2.1 AA Compliance Checklist
Perceivable
1.1.1 Non-text Content: All images have alt text
1.3.1 Info and Relationships: Semantic HTML structure
1.3.2 Meaningful Sequence: Logical reading order
1.3.3 Sensory Characteristics: No instructions based on shape/location alone
1.4.1 Use of Color: Information not conveyed by color alone
1.4.3 Contrast (Minimum): 4.5:1 for normal text, 3:1 for large text
1.4.4 Resize Text: Text can be resized to 200%
1.4.10 Reflow: Content reflows at 320px width
1.4.11 Non-text Contrast: 3:1 contrast for UI components
1.4.12 Text Spacing: Text remains readable with increased spacing
1.4.13 Content on Hover: Tooltips dismissable and persistent
Operable
2.1.1 Keyboard: All functionality available via keyboard
2.1.2 No Keyboard Trap: Focus can move away from all elements
2.4.1 Bypass Blocks: Skip navigation links provided
2.4.2 Page Titled: All pages have descriptive titles
2.4.3 Focus Order: Logical focus order
2.4.4 Link Purpose: Link text describes destination
2.4.5 Multiple Ways: Multiple ways to find pages (navigation, search)
2.4.6 Headings and Labels: Descriptive headings and labels
2.4.7 Focus Visible: Visible focus indicators
Understandable
3.1.1 Language of Page: HTML lang attribute set
3.2.1 On Focus: No context changes on focus alone
3.2.2 On Input: No context changes on input alone
3.2.3 Consistent Navigation: Navigation consistent across pages
3.2.4 Consistent Identification: Components identified consistently
3.3.1 Error Identification: Form errors clearly identified
3.3.2 Labels or Instructions: Form inputs have labels
3.3.3 Error Suggestion: Error messages suggest corrections
3.3.4 Error Prevention: Confirmations for critical actions
Robust
4.1.1 Parsing: Valid HTML
4.1.2 Name, Role, Value: All UI components have accessible names
4.1.3 Status Messages: Status messages use ARIA live regions
🎨 Design System Accessibility
Color Palette
All colors meet WCAG AA contrast requirements:
Background |
Text Color |
Contrast Ratio |
WCAG AA |
|---|---|---|---|
#ffffff (White) |
#1f2937 (Gray-900) |
14.7:1 |
✅ Pass |
#f9fafb (Gray-50) |
#1f2937 (Gray-900) |
13.8:1 |
✅ Pass |
#10b981 (Primary) |
#ffffff (White) |
3.4:1 |
✅ Pass (Large Text) |
#ef4444 (Danger) |
#ffffff (White) |
4.5:1 |
✅ Pass |
Typography
Base Font Size: 16px (1rem)
Line Height: 1.5 (minimum for readability)
Font Family: System fonts for maximum compatibility
Letter Spacing: Normal (not too tight)
Interactive Elements
Minimum Touch Target: 44x44px (WCAG 2.5.5)
Focus Indicator: 2px solid ring, offset by 2px
Hover State: Visible color change
Active State: Distinct from hover
🚀 Best Practices for Developers
1. Use Semantic HTML
<!-- ✅ Good -->
<nav><ul><li><a href="...">Home</a></li></ul></nav>
<main><h1>Page Title</h1><p>Content...</p></main>
<footer>...</footer>
<!-- ❌ Bad -->
<div class="nav">...</div>
<div class="content">...</div>
<div class="footer">...</div>
2. Add ARIA Labels
<!-- ✅ Good -->
<button aria-label="Close dialog">
<svg aria-hidden="true">...</svg>
</button>
<!-- ❌ Bad -->
<button><svg>...</svg></button>
3. Manage Focus
// ✅ Good - Focus management in modals
onMount(() => {
if (isOpen) {
cleanupFocusTrap = trapFocus(modalEl);
}
});
onDestroy(() => {
if (cleanupFocusTrap) {
cleanupFocusTrap();
}
});
4. Announce Dynamic Changes
// ✅ Good - Announce form submission
async function handleSubmit() {
try {
await saveData();
announce('Changes saved successfully', 'polite');
} catch (error) {
announce('Error: Failed to save changes', 'assertive');
}
}
5. Keyboard Event Handling
<!-- ✅ Good - Support both mouse and keyboard -->
<div
role="button"
tabindex="0"
on:click={handleClick}
on:keydown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handleClick();
}
}}
>
Click me
</div>
📞 Reporting Accessibility Issues
If you encounter any accessibility barriers while using KoproGo, please report them:
Email: accessibility@koprogo.com
GitHub Issues: Label with
accessibilityExpected Response: Within 2 business days
📖 Resources
🔄 Continuous Improvement
This is a living document. We continuously improve our accessibility:
Monthly Audits: Automated axe-core scans
Quarterly Reviews: Manual testing with assistive technologies
User Feedback: Incorporating feedback from users with disabilities
Training: Regular accessibility training for all developers