Photo Management (per specs/photo-management.md): - Sharp integration for 3-size compression (thumb/medium/full) - WebP output with 80-90% quality - Client-side compression with browser-image-compression - PhotoUpload component with camera/drag-drop support - Upload API with bulk support and stats endpoint Testing: - Backend: Jest tests for all major API endpoints - Frontend: Vitest tests for utilities and API clients - CI: Updated Forgejo workflow for test execution Specs (100% coverage): - visitor-management.md (Phase 8) - messaging.md (Phase 9) - audit-and-documents.md (Phase 10) - accessibility-i18n.md (Phase 11) - hardware-integration.md (Phase 12) - advanced-features.md (Phase 13) Documentation: - OpenAPI 3.0 spec (docs/openapi.yaml) - All endpoints documented with schemas
2.9 KiB
2.9 KiB
Feature Spec: Accessibility & Internationalization
Priority: 🟢 Important
Phase: 11
Status: ✅ Implemented
Overview
Make the application accessible to all users regardless of ability or language. WCAG 2.1 AA compliance.
Accessibility (a11y)
WCAG 2.1 AA Requirements
Perceivable
- Text alternatives for images
- Color contrast ratio ≥ 4.5:1
- Text resizable to 200%
- Content reflows at 320px width
Operable
- Full keyboard navigation
- Focus visible indicators
- Skip to main content link
- Touch targets ≥ 44x44px
- No keyboard traps
Understandable
- Language attribute on HTML
- Consistent navigation
- Error identification
- Labels for form inputs
Robust
- Valid HTML
- ARIA roles where needed
- Screen reader compatible
Implementation
CSS Utilities
.sr-only /* Screen reader only */
.focus-visible /* Focus ring */
.high-contrast /* High contrast mode */
.reduced-motion /* Respects prefers-reduced-motion */
React Hooks
usePrefersReducedMotion()- Detect motion preferenceuseFocusTrap(ref)- Trap focus in modals
Components
VisuallyHidden- Hide but keep in DOMSkipLink- Skip to main contentLiveRegion- Announce to screen readers
Internationalization (i18n)
Supported Languages
- English (en) - Default
- Spanish (es) - Primary translation
Implementation
Library
react-i18nextfor translationsi18next-browser-languagedetectorfor auto-detection
Translation Structure
/frontend/src/locales/
├── en/
│ └── translation.json
└── es/
└── translation.json
Usage
import { useTranslation } from 'react-i18next';
function Component() {
const { t } = useTranslation();
return <h1>{t('dashboard.title')}</h1>;
}
Translation Keys
Common
common.save,common.cancel,common.deletecommon.loading,common.errorcommon.yes,common.no
Navigation
nav.dashboard,nav.tasks,nav.roomsnav.batches,nav.supplies
Forms
form.required,form.invalidform.submit,form.cancel
User Preferences
PreferencesContext
theme: 'light' | 'dark' | 'system'language: 'en' | 'es'fontSize: 'small' | 'medium' | 'large'highContrast: booleanreducedMotion: booleansoundEnabled: booleannotificationsEnabled: booleancompactMode: boolean
Persistence
- Stored in localStorage
- Synced across tabs
- Applied on app load
Testing
Accessibility Testing
- Lighthouse accessibility audit
- axe-core browser extension
- Manual keyboard navigation test
- Screen reader testing (VoiceOver, NVDA)
i18n Testing
- All strings extracted to JSON
- No hardcoded strings in components
- RTL layout support (future)