critical priority medium complexity testing pending frontend specialist Tier 5

Acceptance Criteria

All interactive elements in AttachmentPickerUI, AttachmentThumbnailGrid, and AttachmentPreviewModal have a minimum touch target size of 44×44 logical pixels, verified by Semantics tree size assertions in flutter_test
Every non-decorative image renders with a non-empty Semantics label (WCAG 1.1.1 — non-text content)
All structural groupings (thumbnail grid, action bar) expose correct Semantics roles so screen readers announce them correctly (WCAG 1.3.1 — info and relationships)
Text contrast ratio ≥ 4.5:1 for all body and label text against the design token background colors, verified using a contrast ratio tool against the token hex values
UI component contrast ratio ≥ 3:1 for icon buttons, borders, and focus indicators against adjacent backgrounds (WCAG 1.4.3 / 1.4.11)
Every interactive element has a visible and distinguishable focus indicator when navigated via keyboard/switch access (WCAG 2.4.7)
Each screen section and interactive group has a descriptive heading or label announced by VoiceOver/TalkBack (WCAG 2.4.6 — headings and labels)
Status messages (upload progress, error, limit reached) are announced via Semantics.liveRegion or equivalent so assistive technology users are informed without focus movement (WCAG 4.1.3 — status messages)
Manual VoiceOver walkthrough on iOS completes without any unlabelled or silent interactive element
Manual TalkBack walkthrough on Android completes without any unlabelled or silent interactive element
A WCAG 2.2 AA compliance checklist document is produced covering criteria 1.1.1, 1.3.1, 1.4.3, 2.4.6, and 4.1.3 with pass/fail/NA status for each component
All identified violations are fixed before this task is marked done — no deferred violations permitted for critical-priority items

Technical Requirements

frameworks
Flutter
flutter_test
performance requirements
Semantics tree audit tests complete within the normal widget test suite run time (no additional CI overhead beyond 30 seconds)
security requirements
Audit must confirm that sensitive file names or user PII surfaced in attachment thumbnails are not inadvertently read aloud in full by screen readers — use truncated Semantics labels where appropriate
ui components
AttachmentPickerUI
AttachmentThumbnailGrid
AttachmentPreviewModal

Execution Context

Execution Tier
Tier 5

Tier 5 - 253 tasks

Can start after Tier 4 completes

Implementation Notes

Start with automated meetsGuideline assertions — these catch the majority of size and label violations quickly. Then move to manual walkthroughs for nuanced issues (reading order, grouped announcements). For contrast checks, extract the actual hex values from the design token Dart constants and run them through a WCAG contrast calculator (e.g. webaim.org/resources/contrastchecker locally scripted).

When fixing violations: prefer Semantics widget wrappers or ExcludeSemantics over modifying widget structure. For live region announcements (upload progress, errors), use SemanticsService.announce() or Semantics(liveRegion: true) wrappers around status text. This is a critical-priority task for Blindeforbundet (screen reader users) and NHF (cognitive and motor accessibility users) — do not defer any violation.

Testing Requirements

Use flutter_test's expect(tester, meetsGuideline(androidTapTargetGuideline)) and expect(tester, meetsGuideline(iOSTapTargetGuideline)) for all three components. Use expect(tester, meetsGuideline(labeledTapTargetGuideline)) for unlabelled interactive elements. Write explicit findsOneWidget assertions on Semantics nodes with specific label strings for every icon button and image. Perform manual walkthroughs on a physical iOS device (VoiceOver) and physical or emulated Android device (TalkBack) following a scripted test scenario: open picker, select source, view thumbnail, open preview modal, close modal.

Record findings in a structured checklist.

Component
Attachment Preview Modal
ui low
Epic Risks (4)
medium impact medium prob dependency

Flutter does not include a first-party PDF renderer. Third-party packages (e.g., flutter_pdfview, syncfusion_flutter_pdf) have inconsistent accessibility support, may not honour dynamic type scaling, and can introduce large binary size increases. Choosing the wrong package late in development risks rework or an inaccessible PDF experience for Blindeforbundet users.

Mitigation & Contingency

Mitigation: Evaluate and spike two PDF rendering packages (flutter_pdfview and pdfx) in the first task of this epic before committing to implementation. Criteria: VoiceOver compatibility, dynamic type support, APK/IPA size delta, and licence. Document the decision in an ADR.

Contingency: If no package meets accessibility requirements, fall back to opening PDFs in the system browser via url_launcher, which inherits the OS's accessible PDF viewer. Display a clear 'Opening in external viewer' message to set user expectation.

medium impact medium prob technical

Flutter's Semantics API for live region announcements (analogous to aria-live) has known gaps on Android for dynamic content updates. Upload progress announcements required by the accessibility user story may not fire reliably on Android devices used by HLF and NHF members.

Mitigation & Contingency

Mitigation: Use SemanticsService.announce() for imperative announcements at each upload state transition rather than relying on declarative Semantics widget tree updates. Test on a physical Android device with TalkBack enabled during development, not only on iOS with VoiceOver.

Contingency: If SemanticsService.announce() proves unreliable, implement a persistent accessible status banner at the top of the screen that reflects the current upload state as plain text, satisfying the WCAG success criterion through a visual + programmatic mechanism.

low impact high prob technical

iOS and Android file picker behaviour diverges significantly: MIME type filtering works reliably on Android but is advisory on iOS (users can still navigate to and select non-compliant files via the Files app). This could allow unsupported file types to reach the upload service, causing validation failures with a confusing user experience.

Mitigation & Contingency

Mitigation: Rely on the AttachmentUploadService (Epic 2) as the authoritative MIME validation gate, regardless of platform. In the UI, re-validate the picked file's extension/MIME after selection and show an inline plain-language error ('Only PDF, JPEG, and PNG files are supported') before even calling the service.

Contingency: If users consistently hit the error due to iOS file picker limitations, add a user-facing help tooltip on the picker sheet explaining the supported file types, reducing support volume while the underlying OS limitation persists.

high impact medium prob scope

WCAG 2.2 AA compliance for three new interactive components (picker, grid, modal) with file system integration, role-gated actions, and live regions is a significant accessibility surface area. An incomplete audit before release could result in the feature being unusable for Blindeforbundet screen reader users at launch.

Mitigation & Contingency

Mitigation: Allocate a dedicated accessibility audit task at the end of the epic using the accessibility-test-harness (619) and wcag-compliance-checker (620) components already in the project. Include at least one manual test session on a physical device with VoiceOver enabled. Fail the epic's definition of done if any WCAG 2.2 AA violation remains open.

Contingency: If critical accessibility issues are found late, gate the feature behind the org-level attachments_enabled feature flag and only enable it for NHF (the requesting org) after a targeted fix cycle, rather than delaying the release for all organisations.