Written and testable before Phase 1 build starts, not treated as later QA, per the risk register.
Context
Issue #87 already found the mobile app has zero accessibility* props anywhere in mobile/src: a glyph-only ✓/○ toggle with no role or state, an unlabeled "Delete" text control, and an error banner that isn't a live region. Decision 0008 commits the first vertical slice (Contacts CRUD + the generic CRUD component) to being "tested, accessible" — and since that generic pattern gets copied into every later Phase 1 screen (#118), the baseline needs to exist before that build starts, not be bolted on after.
Deliverable
A short written baseline (e.g. docs/accessibility.md) Phase 1 PRs can be checked against:
- Interactive controls — every
Pressable/TouchableOpacity used as a button, toggle, or link sets accessibilityRole, and accessibilityState where state exists (e.g. { checked } on the completion toggle). No icon/glyph-only control ships without accessibilityLabel.
- Live feedback — error banners and validation messages use
accessibilityLiveRegion="polite" (or AccessibilityInfo.announceForAccessibility) so failures are announced, not just displayed.
- Text & touch targets — minimum 44×44pt touch targets; text respects OS font-scaling (no fixed
fontSize that ignores Dynamic Type); color contrast meets a stated minimum (e.g. WCAG 2.1 AA, 4.5:1 body text).
- Forms — every input has a programmatically-linked label; errors are conveyed via
accessibilityLabel/accessibilityHint, not color alone.
- Screen reader flow — reading order matches visual order; decorative icons/images are hidden from the accessibility tree.
Acceptance criteria
Related: informs #118 · resolves finding in #87 · tracked in #72
Written and testable before Phase 1 build starts, not treated as later QA, per the risk register.
Context
Issue #87 already found the mobile app has zero
accessibility*props anywhere inmobile/src: a glyph-only ✓/○ toggle with no role or state, an unlabeled "Delete" text control, and an error banner that isn't a live region. Decision 0008 commits the first vertical slice (Contacts CRUD + the generic CRUD component) to being "tested, accessible" — and since that generic pattern gets copied into every later Phase 1 screen (#118), the baseline needs to exist before that build starts, not be bolted on after.Deliverable
A short written baseline (e.g.
docs/accessibility.md) Phase 1 PRs can be checked against:Pressable/TouchableOpacityused as a button, toggle, or link setsaccessibilityRole, andaccessibilityStatewhere state exists (e.g.{ checked }on the completion toggle). No icon/glyph-only control ships withoutaccessibilityLabel.accessibilityLiveRegion="polite"(orAccessibilityInfo.announceForAccessibility) so failures are announced, not just displayed.fontSizethat ignores Dynamic Type); color contrast meets a stated minimum (e.g. WCAG 2.1 AA, 4.5:1 body text).accessibilityLabel/accessibilityHint, not color alone.Acceptance criteria
Related: informs #118 · resolves finding in #87 · tracked in #72