Add WCAG 2.2 AA semantics to ThumbnailGrid
epic-document-attachments-ui-task-008 — Apply Semantics widgets to AttachmentThumbnailGrid: semantic labels for each thumbnail including file name and type, accessible delete button labels ('Delete attachment: filename.pdf'), minimum 44x44 pt touch targets for all interactive elements, and live region announcements via SemanticsService when an attachment is deleted.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 2 - 518 tasks
Can start after Tier 1 completes
Implementation Notes
Wrap each thumbnail GridItem in a Semantics widget — do not rely on Flutter's automatic semantics merging for this case, as merged semantics from an Image + IconButton stack often produce incorrect labels. Use excludeSemantics: true on the Image widget itself if the parent Semantics already provides the full label, to prevent duplicate announcements. For the SemanticsService.announce call, trigger it inside the BLoC's state listener (BlocListener) after the deletion is confirmed, not optimistically before the async operation completes. This project has WCAG 2.2 AA as a hard requirement (NHF, Blindeforbundet users with screen readers) — treat this task as non-negotiable quality work.
Testing Requirements
Widget tests using flutter_test: (1) render AttachmentThumbnailGrid with two mock attachments and use tester.getSemantics(find.byType(Image).first) to assert the correct label, (2) find the delete button semantics node and assert label contains 'Delete attachment:' and the filename, (3) simulate a delete action and assert SemanticsService.announce was called with the correct message (mock SemanticsService via a test double). Manual accessibility audit on iOS with VoiceOver enabled via TestFlight build to verify all labels are read aloud correctly.
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.
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.
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.
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.