Skip to content

feat(mobile): audit W3-C accessibility semantics - #5076

Merged
iscekic merged 43 commits into
mainfrom
audit-w3c-a11y-semantics-1ab3
Aug 17, 2026
Merged

iscekic merged 43 commits into
mainfrom
audit-w3c-a11y-semantics-1ab3

Conversation

@iscekic

@iscekic iscekic commented Aug 6, 2026 •

Copy link
Copy Markdown
Collaborator

The user: Mobile controls, forms, Markdown, uploads, reduced-motion sheets, and deletion flows expose clearer screen-reader semantics and focus behavior.

The product manager: Users receive labeled choices, readable disabled states, upload progress and outcomes, structured Markdown tables, reduced-motion action sheets, and reliable focus after dismissals and deletions.

The maintainer: Shared accessibility contracts cover status announcements, radio groups, form labels, image alt policy, motion policy, hidden routes, Modal focus lifecycle, stable removal anchors, and upload state semantics.

Human steps: No human step is needed before or after merge.

Visual Changes: N/A.

E2E: bot-e2e — runtime verification was blocked by the Android CLI environment after the bundle started; unit and mounted tests are the evidence.

CI note: A main-line regression in the selectable Markdown error assertion was fixed in this branch because the merge ref inherited the failing main test.

Out of scope: KiloChat and KiloClaw files remain unchanged per the approved plan.

@iscekic iscekic self-assigned this Aug 6, 2026
@kilo-code-bot

kilo-code-bot Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

Incremental review of 2 changed files: the previous focus-restore timer finding is resolved — reopening now cancels the pending restore via focusTimerRef, the dismiss allowance is bumped to 400ms, and both paths are covered by updated tests.

Files Reviewed (2 files, incremental since 9e1976a)
  • apps/mobile/src/components/pr-review/discussion/reactions-row.tsx — previous WARNING resolved: openPicker clears the pending timer and the slide-out allowance is now 400ms with documented rationale
  • apps/mobile/src/components/pr-review/discussion/reactions-row.test.tsx — new close-reopen cancellation test; helper timing updated to 400ms, consistent with the constant
Previous Review Summaries (5 snapshots, latest commit 9e1976a)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 9e1976a)

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0

Fix these issues in Kilo Cloud

Issue Details (click to expand)

WARNING

File Line Issue
apps/mobile/src/components/pr-review/discussion/reactions-row.tsx 74 Focus-restore setTimeout is decoupled from actual Modal dismissal: on iOS it can fire while the sheet is still presented (silently dropping focus restore), and a close-then-reopen within 300ms lets a stale timer fire against the re-presented sheet. The removed per-platform machinery (Modal.onDismiss + guarded fallback) handled both cases.
Files Reviewed (8 files, incremental since 6a493b5)
  • apps/mobile/src/components/agents/attachment-preview-strip.mounted.test.tsx - test pruning; remaining helpers (chipBody, labeledPressables, pressableByLabel) all still used
  • apps/mobile/src/components/agents/markdown-renderer.test.ts - heading-semantics assertions trimmed; imports still used
  • apps/mobile/src/components/agents/markdown-table.test.ts - helper/test pruning; findAll/findFirst/TableRow still used, no dangling references
  • apps/mobile/src/components/agents/session-row-accessibility-label.test.ts - removed needsInput test; behavior still covered by other cases in the same file
  • apps/mobile/src/components/pr-review/discussion/reaction-picker-sheet.tsx - dismiss machinery and onDismiss prop removed; sole consumer updated, no stale references
  • apps/mobile/src/components/pr-review/discussion/reactions-row.test.tsx - tests rewritten for the timer-based restore; consistent with new implementation
  • apps/mobile/src/components/pr-review/discussion/reactions-row.tsx - 1 issue (fixed-delay focus restore replaces per-platform dismissal signals)
  • apps/mobile/src/components/ui/accessible-status.mounted.test.tsx - default error-tone test removed; source unchanged

Previous review (commit 6a493b5)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (23 files, incremental since 77193c6)
  • apps/mobile/src/components/agents/attachment-preview-strip.mounted.test.tsx - geometry helper cleanup, no dangling refs
  • apps/mobile/src/components/agents/file-part-renderer.test.ts - test file deleted (source unchanged)
  • apps/mobile/src/components/agents/markdown-a11y.test.ts - test consolidation, imports still used
  • apps/mobile/src/components/agents/markdown-table.test.ts - test consolidation
  • apps/mobile/src/components/agents/markdown-table.tsx - pluralizeCount simplification correct for column/row
  • apps/mobile/src/components/agents/model-selector.tsx - removed redundant accessible={false} (RN View default)
  • apps/mobile/src/components/code-reviewer/manual-review-screen.tsx - formFieldA11y output verified identical to replaced inline expression
  • apps/mobile/src/components/consent/consent-card.tsx - AccessibleStatus handles null message by design
  • apps/mobile/src/components/organization/invite-member-sheet.tsx - removed dead accessibilityLabel override (FormField computes its own label after prop spread)
  • apps/mobile/src/components/organization/low-balance-alert-sheet.tsx - same dead-override cleanup
  • apps/mobile/src/components/organization/member-limit-sheet.tsx - same dead-override cleanup
  • apps/mobile/src/components/pr-review/discussion/reactions-row.test.tsx - reanimated mock removal safe (no reanimated imports in pr-review at HEAD)
  • apps/mobile/src/components/pr-review/pr-review-pending-comment-row.test.ts - test file deleted (source unchanged)
  • apps/mobile/src/components/pr-review/pr-review-pending-comment-row.tsx - doc comment only
  • apps/mobile/src/components/pr-review/pr-review-submit.tsx - chip className ternaries verified semantically equivalent
  • apps/mobile/src/components/ui/accessible-status.mounted.test.tsx - test rename/trim
  • apps/mobile/src/components/ui/radio-group.test.ts - test consolidation
  • apps/mobile/src/components/ui/radio-group.tsx - RadioItemA11y export removal safe (no external importers)
  • apps/mobile/src/lib/a11y/announcing-toast.ts - wrapper inlined, behavior unchanged
  • apps/mobile/src/lib/a11y/motion.test.ts - test file deleted
  • apps/mobile/src/lib/a11y/motion.ts - reduceMotion field removal safe (no consumers)
  • apps/mobile/src/lib/hooks/use-theme-colors.contrast.test.ts - contrast assertions moved here; helpers and imports verified present
  • apps/mobile/src/lib/pr-review/diff/syntax-colors.test.ts - contrast tests moved out; exports still resolve

Previous review (commit 77193c6)

Status: No Issues Found | Recommendation: Merge

Executive Summary

Incremental review of the changes since the previous review (fe630770): two origin/main merges (ddc76765b, 6d8ce28a7) and one PR-authored commit (77193c6d2, icon-mock alignment). The mainline content of the merges is out of scope; the merge conflict resolutions in the PR's mobile files were verified hunk-by-hunk — each correctly combines main's @/components/ui/icons deep-import barrel with the PR's accessibility changes (PR additions such as RotateCcw, announceForA11y/moveA11yFocus, AccessibleStatus, and RadioGroup imports are preserved). Every icon imported from the barrel in resolved files (AlertCircle, File, RotateCcw, X, SmilePlus, Trash2, Check, Mic, Square, SearchX, ServerCrash, WifiOff) is exported by apps/mobile/src/components/ui/icons.ts at HEAD, the 77193c6d2 mock updates match each source file's imports exactly, and no lucide-react-native imports or stale mocks remain in apps/mobile/src at HEAD 77193c6d2. No new memory-leak surface and no issues found; the previous full-review verdict on the remaining files is unchanged.

Files Reviewed (16 files, incremental)
  • apps/mobile/src/app/_layout.tsx (merge resolution)
  • apps/mobile/src/components/agents/attachment-preview-strip.mounted.test.tsx
  • apps/mobile/src/components/agents/attachment-preview-strip.tsx (merge resolution)
  • apps/mobile/src/components/agents/file-part-renderer.test.ts
  • apps/mobile/src/components/agents/file-part-renderer.tsx
  • apps/mobile/src/components/agents/question-card.mounted.test.tsx
  • apps/mobile/src/components/agents/question-card.tsx
  • apps/mobile/src/components/pr-review/discussion/reaction-picker-sheet.tsx (merge resolution)
  • apps/mobile/src/components/pr-review/discussion/reactions-row.test.tsx
  • apps/mobile/src/components/pr-review/discussion/reactions-row.tsx (merge resolution)
  • apps/mobile/src/components/pr-review/pr-review-pending-comment-row.test.ts
  • apps/mobile/src/components/pr-review/pr-review-pending-comment-row.tsx (merge resolution)
  • apps/mobile/src/components/query-error.tsx (merge resolution)
  • apps/mobile/src/components/security-agent/settings-pill-group.tsx (merge resolution)
  • apps/mobile/src/components/ui/icons.ts (barrel export verification)
  • apps/mobile/src/components/voice-input-control.tsx (merge resolution)

Previous review (commit fe63077)

Status: No Issues Found | Recommendation: Merge

Executive Summary

Incremental review of the 13 PR-authored commits since the previous review (056f042b; the large raw diff is the ba4652ca2 main merge, whose mainline changes are out of scope): the reduced-motion action-sheet removal and direct useActionSheet adoption, the announceForA11y failure-boundary consolidation (verified the shared helper still swallows native failures at HEAD), the markdown-table single-announcement fix with containsPressable, the tap-anywhere attachment retry restore, the liveIdsRef-only stale-upload guard (UUID ids make the dropped generation check equivalent), the cleanup-based reveal-focus cancellation in _layout.tsx, and the searchInputRef prop plumbing were all verified against HEAD fe630770 — no dangling references to deleted modules, no new memory-leak surface (the module-level ref singleton was removed), and no issues found. The previous full-review verdict on the remaining 110 files is unchanged.

Files Reviewed (48 files, incremental)
  • apps/mobile/src/app/(app)/agent-chat/new.tsx
  • apps/mobile/src/app/_layout.tsx
  • apps/mobile/src/components/agents/attachment-preview-strip.mounted.test.tsx
  • apps/mobile/src/components/agents/attachment-preview-strip.tsx
  • apps/mobile/src/components/agents/chat-composer.tsx
  • apps/mobile/src/components/agents/chat-markdown-text.tsx
  • apps/mobile/src/components/agents/file-part-renderer.test.ts
  • apps/mobile/src/components/agents/file-part-renderer.tsx
  • apps/mobile/src/components/agents/markdown-a11y.ts
  • apps/mobile/src/components/agents/markdown-table.test.ts
  • apps/mobile/src/components/agents/markdown-table.tsx
  • apps/mobile/src/components/agents/remote-session-row.tsx
  • apps/mobile/src/components/agents/session-list-content.tsx
  • apps/mobile/src/components/agents/session-list-screen.tsx
  • apps/mobile/src/components/agents/session-list-search-header.tsx
  • apps/mobile/src/components/agents/session-row.tsx
  • apps/mobile/src/components/agents/use-continue-session.ts
  • apps/mobile/src/components/app-root-providers.tsx
  • apps/mobile/src/components/notifications-screen.tsx
  • apps/mobile/src/components/organization/invited-member-row.tsx
  • apps/mobile/src/components/organization/member-row.tsx
  • apps/mobile/src/components/pr-review/discussion/reaction-picker-sheet.tsx
  • apps/mobile/src/components/pr-review/discussion/reaction-pill-a11y.test.ts (deleted)
  • apps/mobile/src/components/pr-review/discussion/reaction-pill-a11y.ts (deleted)
  • apps/mobile/src/components/pr-review/discussion/reactions-row.test.tsx
  • apps/mobile/src/components/pr-review/discussion/reactions-row.tsx
  • apps/mobile/src/components/preferences-screen.tsx
  • apps/mobile/src/components/profile-credits-card.tsx
  • apps/mobile/src/components/security-agent/dashboard-screen.tsx
  • apps/mobile/src/components/ui/form-field-a11y.test.ts
  • apps/mobile/src/components/ui/form-field-a11y.ts
  • apps/mobile/src/components/ui/image.test.ts (deleted)
  • apps/mobile/src/components/ui/image.tsx
  • apps/mobile/src/components/ui/reduced-motion-sheet.tsx (deleted)
  • apps/mobile/src/components/ui/session-row.tsx
  • apps/mobile/src/lib/a11y/announcing-toast.test.ts
  • apps/mobile/src/lib/a11y/announcing-toast.ts
  • apps/mobile/src/lib/a11y/hidden-route.test.ts (deleted)
  • apps/mobile/src/lib/a11y/hidden-route.ts (deleted)
  • apps/mobile/src/lib/a11y/motion-sheet.test.ts (deleted)
  • apps/mobile/src/lib/a11y/motion.test.ts
  • apps/mobile/src/lib/a11y/motion.ts
  • apps/mobile/src/lib/a11y/status-announcement.ts
  • apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.test.ts
  • apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.ts
  • apps/mobile/src/lib/hooks/use-session-mutations.test.ts
  • apps/mobile/src/lib/hooks/use-session-mutations.ts
  • apps/mobile/src/lib/hooks/use-theme-colors.contrast.test.ts
Previously Reviewed (110 files, verdict unchanged)
  • apps/mobile/src/app/(app)/(tabs)/(3_profile)/code-reviewer/[scope]/[platform]/(edit)/repos.tsx
  • apps/mobile/src/app/(app)/agent-chat/instance-picker.tsx
  • apps/mobile/src/app/(app)/agent-chat/new.tsx
  • apps/mobile/src/app/(app)/agent-chat/repo-picker.tsx
  • apps/mobile/src/app/_layout.tsx
  • apps/mobile/src/components/agents/attachment-chip-description.ts
  • apps/mobile/src/components/agents/attachment-preview-strip.mounted.test.tsx
  • apps/mobile/src/components/agents/attachment-preview-strip.test.ts
  • apps/mobile/src/components/agents/attachment-preview-strip.tsx
  • apps/mobile/src/components/agents/chat-composer.tsx
  • apps/mobile/src/components/agents/chat-markdown-text.tsx
  • apps/mobile/src/components/agents/file-part-renderer.test.ts
  • apps/mobile/src/components/agents/file-part-renderer.tsx
  • apps/mobile/src/components/agents/markdown-a11y.test.ts
  • apps/mobile/src/components/agents/markdown-a11y.ts
  • apps/mobile/src/components/agents/markdown-renderer.test.ts
  • apps/mobile/src/components/agents/markdown-renderer.ts
  • apps/mobile/src/components/agents/markdown-table.test.ts
  • apps/mobile/src/components/agents/markdown-table.tsx
  • apps/mobile/src/components/agents/model-selector.tsx
  • apps/mobile/src/components/agents/platform-filter-modal.tsx
  • apps/mobile/src/components/agents/question-card.mounted.test.tsx
  • apps/mobile/src/components/agents/question-card.tsx
  • apps/mobile/src/components/agents/remote-session-row.tsx
  • apps/mobile/src/components/agents/session-list-content.tsx
  • apps/mobile/src/components/agents/session-list-search-header.tsx
  • apps/mobile/src/components/agents/session-pagination-header.tsx
  • apps/mobile/src/components/agents/session-row-accessibility-label.test.ts
  • apps/mobile/src/components/agents/session-row.tsx
  • apps/mobile/src/components/agents/suggestion-card.tsx
  • apps/mobile/src/components/agents/use-continue-session.ts
  • apps/mobile/src/components/agents/use-session-list-auto-scroll.ts
  • apps/mobile/src/components/app-root-providers.tsx
  • apps/mobile/src/components/code-reviewer/bitbucket-overview.tsx
  • apps/mobile/src/components/code-reviewer/manual-review-screen.tsx
  • apps/mobile/src/components/code-reviewer/option-list.tsx
  • apps/mobile/src/components/code-reviewer/platform-overview-screen.tsx
  • apps/mobile/src/components/code-reviewer/review-list-screen.tsx
  • apps/mobile/src/components/consent/consent-card.tsx
  • apps/mobile/src/components/empty-state.tsx
  • apps/mobile/src/components/login/email-otp-form.tsx
  • apps/mobile/src/components/notifications-screen.tsx
  • apps/mobile/src/components/organization/invite-member-sheet.tsx
  • apps/mobile/src/components/organization/invited-member-row.tsx
  • apps/mobile/src/components/organization/low-balance-alert-sheet.tsx
  • apps/mobile/src/components/organization/member-limit-sheet.tsx
  • apps/mobile/src/components/organization/member-row.tsx
  • apps/mobile/src/components/pr-review/diff/pr-diff-file-list-header.tsx
  • apps/mobile/src/components/pr-review/discussion/reaction-picker-sheet.tsx
  • apps/mobile/src/components/pr-review/discussion/reaction-pill-a11y.test.ts
  • apps/mobile/src/components/pr-review/discussion/reaction-pill-a11y.ts
  • apps/mobile/src/components/pr-review/discussion/reactions-row.test.tsx
  • apps/mobile/src/components/pr-review/discussion/reactions-row.tsx
  • apps/mobile/src/components/pr-review/merge/pr-merge-partial-success-banner.test.ts
  • apps/mobile/src/components/pr-review/merge/pr-merge-partial-success-banner.tsx
  • apps/mobile/src/components/pr-review/merge/pr-merge-sheet-parts.tsx
  • apps/mobile/src/components/pr-review/pr-review-comment-composer.tsx
  • apps/mobile/src/components/pr-review/pr-review-discussion-tab.tsx
  • apps/mobile/src/components/pr-review/pr-review-pending-comment-row.test.ts
  • apps/mobile/src/components/pr-review/pr-review-pending-comment-row.tsx
  • apps/mobile/src/components/pr-review/pr-review-submit.tsx
  • apps/mobile/src/components/preferences-screen.tsx
  • apps/mobile/src/components/profile-credits-card.tsx
  • apps/mobile/src/components/query-error.tsx
  • apps/mobile/src/components/security-agent/analysis-settings-screen.tsx
  • apps/mobile/src/components/security-agent/dashboard-screen.tsx
  • apps/mobile/src/components/security-agent/finding-filter-modal.tsx
  • apps/mobile/src/components/security-agent/repository-settings-screen.tsx
  • apps/mobile/src/components/security-agent/settings-pill-group.tsx
  • apps/mobile/src/components/ui/accessible-status.mounted.test.tsx
  • apps/mobile/src/components/ui/accessible-status.tsx
  • apps/mobile/src/components/ui/action-button.tsx
  • apps/mobile/src/components/ui/configure-row.tsx
  • apps/mobile/src/components/ui/form-field-a11y.test.ts
  • apps/mobile/src/components/ui/form-field-a11y.ts
  • apps/mobile/src/components/ui/form-field.tsx
  • apps/mobile/src/components/ui/image.test.ts
  • apps/mobile/src/components/ui/image.tsx
  • apps/mobile/src/components/ui/radio-group.test.ts
  • apps/mobile/src/components/ui/radio-group.tsx
  • apps/mobile/src/components/ui/reduced-motion-sheet.tsx
  • apps/mobile/src/components/ui/segmented-control.tsx
  • apps/mobile/src/components/ui/session-row.tsx
  • apps/mobile/src/components/voice-input-control.tsx
  • apps/mobile/src/global.css
  • apps/mobile/src/lib/a11y/announce.test.ts
  • apps/mobile/src/lib/a11y/announce.ts
  • apps/mobile/src/lib/a11y/announcing-toast.test.ts
  • apps/mobile/src/lib/a11y/announcing-toast.ts
  • apps/mobile/src/lib/a11y/hidden-route.test.ts
  • apps/mobile/src/lib/a11y/hidden-route.ts
  • apps/mobile/src/lib/a11y/motion-sheet.test.ts
  • apps/mobile/src/lib/a11y/motion.test.ts
  • apps/mobile/src/lib/a11y/motion.ts
  • apps/mobile/src/lib/a11y/status-announcement.test.ts
  • apps/mobile/src/lib/a11y/status-announcement.ts
  • apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.test.ts
  • apps/mobile/src/lib/agent-attachments/use-agent-attachment-upload.ts
  • apps/mobile/src/lib/hooks/use-session-mutations.test.ts
  • apps/mobile/src/lib/hooks/use-session-mutations.ts
  • apps/mobile/src/lib/hooks/use-theme-colors.contrast.test.ts
  • apps/mobile/src/lib/hooks/use-theme-colors.ts
  • apps/mobile/src/lib/pr-review/diff/syntax-colors.test.ts
  • apps/mobile/src/lib/pr-review/diff/syntax-colors.ts
  • apps/mobile/src/lib/pr-review/diff/use-pr-diff-list-scroll.ts
  • apps/mobile/src/lib/pr-review/merge/use-pr-merge-mutations.test.ts
  • apps/mobile/src/lib/pr-review/merge/use-pr-merge-mutations.ts
  • apps/mobile/src/lib/pr-review/use-pr-review-mutations.ts

Previous review (commit 056f042)

Status: No Issues Found | Recommendation: Merge

Executive Summary

Incremental review of the single new PR commit since the previous full review (056f042b, on top of a main merge): the 2-line assertion update in tool-card-output-cap.test.ts correctly tracks main's SelectableText error rendering (TextInput with value) — verified against read-tool-card.tsx and selectable-text.tsx at HEAD; no issues found, and the previous full-review verdict on the remaining 110 files is unchanged.

Files Reviewed (1 file, incremental)
  • apps/mobile/src/components/agents/tool-cards/tool-card-output-cap.test.ts
Previously Reviewed (110 files, verdict unchanged)
  • apps/mobile/src/app/(app)/(tabs)/(3_profile)/code-reviewer/[scope]/[platform]/(edit)/repos.tsx
  • apps/mobile/src/app/(app)/agent-chat/instance-picker.tsx
  • apps/mobile/src/app/(app)/agent-chat/new.tsx
  • apps/mobile/src/app/(app)/agent-chat/repo-picker.tsx
  • apps/mobile/src/app/_layout.tsx
  • apps/mobile/src/components/agents/attachment-chip-description.ts
  • apps/mobile/src/components/agents/attachment-preview-strip.mounted.test.tsx
  • apps/mobile/src/components/agents/attachment-preview-strip.test.ts
  • apps/mobile/src/components/agents/attachment-preview-strip.tsx
  • apps/mobile/src/components/agents/chat-composer.tsx
  • apps/mobile/src/components/agents/chat-markdown-text.tsx
  • apps/mobile/src/components/agents/file-part-renderer.test.ts
  • apps/mobile/src/components/agents/file-part-renderer.tsx
  • apps/mobile/src/components/agents/markdown-a11y.test.ts
  • apps/mobile/src/components/agents/markdown-a11y.ts
  • apps/mobile/src/components/agents/markdown-renderer.test.ts
  • apps/mobile/src/components/agents/markdown-renderer.ts
  • apps/mobile/src/components/agents/markdown-table.test.ts
  • apps/mobile/src/components/agents/markdown-table.tsx
  • apps/mobile/src/components/agents/model-selector.tsx
  • apps/mobile/src/components/agents/platform-filter-modal.tsx
  • apps/mobile/src/components/agents/question-card.mounted.test.tsx
  • apps/mobile/src/components/agents/question-card.tsx
  • apps/mobile/src/components/agents/remote-session-row.tsx
  • apps/mobile/src/components/agents/session-list-content.tsx
  • apps/mobile/src/components/agents/session-list-search-header.tsx
  • apps/mobile/src/components/agents/session-pagination-header.tsx
  • apps/mobile/src/components/agents/session-row-accessibility-label.test.ts
  • apps/mobile/src/components/agents/session-row.tsx
  • apps/mobile/src/components/agents/suggestion-card.tsx
  • apps/mobile/src/components/agents/use-continue-session.ts
  • apps/mobile/src/components/agents/use-session-list-auto-scroll.ts
  • apps/mobile/src/components/app-root-providers.tsx
  • apps/mobile/src/components/code-reviewer/bitbucket-overview.tsx
  • apps/mobile/src/components/code-reviewer/manual-review-screen.tsx
  • apps/mobile/src/components/code-reviewer/option-list.tsx
  • apps/mobile/src/components/code-reviewer/platform-overview-screen.tsx
  • apps/mobile/src/components/code-reviewer/review-list-screen.tsx
  • apps/mobile/src/components/consent/consent-card.tsx
  • apps/mobile/src/components/empty-state.tsx
  • apps/mobile/src/components/login/email-otp-form.tsx
  • apps/mobile/src/components/notifications-screen.tsx
  • apps/mobile/src/components/organization/invite-member-sheet.tsx
  • apps/mobile/src/components/organization/invited-member-row.tsx
  • apps/mobile/src/components/organization/low-balance-alert-sheet.tsx
  • apps/mobile/src/components/organization/member-limit-sheet.tsx
  • apps/mobile/src/components/organization/member-row.tsx
  • apps/mobile/src/components/pr-review/diff/pr-diff-file-list-header.tsx
  • apps/mobile/src/components/pr-review/discussion/reaction-picker-sheet.tsx
  • apps/mobile/src/components/pr-review/discussion/reaction-pill-a11y.test.ts
  • apps/mobile/src/components/pr-review/discussion/reaction-pill-a11y.ts
  • apps/mobile/src/components/pr-review/discussion/reactions-row.test.tsx
  • apps/mobile/src/components/pr-review/discussion/reactions-row.tsx
  • apps/mobile/src/components/pr-review/merge/pr-merge-partial-success-banner.test.ts
  • apps/mobile/src/components/pr-review/merge/pr-merge-partial-success-banner.tsx
  • apps/mobile/src/components/pr-review/merge/pr-merge-sheet-parts.tsx
  • apps/mobile/src/components/pr-review/pr-review-comment-composer.tsx
  • apps/mobile/src/components/pr-review/pr-review-discussion-tab.tsx
  • apps/mobile/src/components/pr-review/pr-review-pending-comment-row.test.ts
  • apps/mobile/src/components/pr-review/pr-review-pending-comment-row.tsx
  • apps/mobile/src/components/pr-review/pr-review-submit.tsx
  • apps/mobile/src/components/preferences-screen.tsx
  • apps/mobile/src/components/profile-credits-card.tsx
  • apps/mobile/src/components/query-error.tsx
  • apps/mobile/src/components/security-agent/analysis-settings-screen.tsx
  • apps/mobile/src/components/security-agent/dashboard-screen.tsx
  • `apps/mobile/src/components/security-agent/finding-filter-modal.tsx

[Snapshot truncated.]

Additional previous summary content was truncated to keep this comment within platform limits.


Reviewed by kimi-k3 · Input: 53.1K · Output: 3.9K · Cached: 160.9K

Review guidance: REVIEW.md from base branch main

@iscekic iscekic added the human-ready The PR is ready for human review. label Aug 6, 2026
iscekic added 2 commits August 6, 2026 17:37
Keep both sides in every conflicted file:

- markdown-renderer.ts: main's shared linkInteractionProps plus the branch's
  heading header role and image-only pass-through.
- markdown-renderer.test.ts: both the heading-semantics suite and main's
  link-interaction suite.
- markdown-table.test.ts: one tree walker (findFirst/findAll) now serves the
  branch's table-semantics suite and main's trigger and two-axis modal suite.
- tool-card-output-cap.test.ts: identical SelectableText assertion, with
  main's explanatory comment.
- app-root-providers.tsx: both OfflineBanner and ReducedMotionSheetHost.
- use-theme-colors.ts: the branch's WCAG AA status hues plus main's
  warnForeground token.
- use-theme-colors.contrast.test.ts: both contrast suites; the warn comment
  now cites the merged hue.

Point main's new part-detail-sheet radio assertions at accessibilityState
`checked`, because the branch moved radio items from `selected` to `checked`.
The hand-rolled non-animated option list existed because
@expo/react-native-action-sheet animates a fixed 225ms presentation.
WCAG 2.3.3 is AAA and scopes non-essential animation; a sheet's own
slide-in is essential presentation motion, so the target is met without
it.

Delete the host component, the mapper, the override hook, and their
tests. Revert the ten call sites to useActionSheet. Keep useMotionPolicy
for the imperative-scroll callers.
iscekic added 12 commits August 6, 2026 18:25
Every form in this branch is disabled-until-valid, so no call site can
reach a focus-to-first-invalid boundary. Only the helper's own test used
it.
One call site, three static props. The module and its test cost more
than the object they built.
One ternary, one call site in the root layout. Also drops the redundant
reveal-focus guard ref: the effect cleanup already cancels the pending
frame before a later render can schedule its own.
announceForA11y already swallows a native accessibility failure, so the
three call-site try/catch layers and the delete toast's try/finally could
never fire. Drop them and the tests that forced the impossible throw;
announce.test.ts owns that guarantee.
Wrapping the primitive in a plain function to add `alt` cost ref
forwarding for all eleven callers, and expo-image already treats `alt` as
an alias for accessibilityLabel. Exactly one caller needs a label, so it
sets accessible/role/label itself.
The session-list screen already owns the search-input ref, so the module
level mirror ref was a second source of truth: a header unmount nulls it
through the callback ref, making correctness depend on mount ordering.
Pass the ref the screen already has.

Inline hasHistoryContent to stay inside the file's max-lines cap.
liveIdsRef already invalidates a removed or reset upload, and ids are
UUIDs, so the generation check on the two upload completions could never
add a rejection. Keep generationRef only where no id exists yet: a reset
during candidate measurement.
ui/SessionRow's `onPress` branch has no caller: both session rows wrap
the primitive in their own labelled Pressable. Labelling it pulled an
agents-layer helper into components/ui, so drop the label and the import.
Dropping the row opacity left disabled preference and notification rows
looking enabled. Mute the title instead: blanket opacity pushed every
label under the 4.5:1 text minimum, while the token does not. The Switch
still renders its own disabled appearance.

Extend the muted-foreground contrast test to `secondary`, the surface
these rows actually use.
The row label sat on an invisible accessible sibling while the cells
stayed in the accessibility tree, so a screen reader read the whole row
and then each cell again.

A row now announces exactly one way. A plain row keeps the linear label
and hides its cells. A row holding a Markdown link or image exposes its
cells and drops the label, so those controls keep their own focus and tap
target — an accessible container would shadow them on iOS.
Moving retry to a 28pt corner button kept the 44pt effective target but
lost the affordance a failed chip has always had: the whole chip retried.
Retry now covers the chip as a sibling of the surface and of Remove, so
neither is shadowed for assistive technology, and Remove renders last so
it still wins the corner it occupies.
The sheet ran its own two-phase presentation: a 200ms constant hand-synced
to Reanimated's 180ms SlideOutDown, chained into a second timer, driving
two pieces of visibility state. Editing either duration would clip or
strand the exit.

`animationType="slide"` makes the platform own enter and exit, so `visible`
is the single source of truth. Android still waits out the slide-out before
restoring focus, because Modal.onDismiss is iOS-only; that is now one timer
with one constant and no coupling to a value in this file.
@iscekic

iscekic commented Aug 6, 2026 •

Copy link
Copy Markdown
Collaborator Author

(bot) ## Finding 2 — colour tokens

The branch values are:

Token main branch
destructive #BE4E3F #B0483A
good #278150 #24784A
warn #9F6612 #956011
info #2563EB #2260EB

Security Agent dashboard — light theme:

Finding 2 — Security Agent dashboard — light theme

Destructive delete confirmation — light theme:

Finding 2 — destructive confirmation — light theme

Security Agent dashboard — dark theme:

Finding 2 — Security Agent dashboard — dark theme

Destructive delete confirmation — dark theme:

Finding 2 — destructive confirmation — dark theme

The human must decide whether to keep or revert the token retune.

Finding 6 — chip retry target

No valid retryable failed attachment chip capture was possible on iOS. The local flow opened both attachment pickers, but the available forced 22 MB PDF failure was rejected before upload as a terminal client-side size error, so no Retry chip rendered. No product code changed.

  • Failed image chip shows a bottom-left retry badge and clear filename: NOT VERIFIED.
  • Tapping anywhere on a failed image or document chip retries: NOT VERIFIED.
  • Tapping the top-right X removes without retrying: NOT VERIFIED.

The Finding 6 screenshot set is missing because the retryable failed-chip state could not be produced. This is an evidence blocker, not a pass.

iscekic added 3 commits August 7, 2026 13:02
…ics-1ab3

# Conflicts:
#	apps/mobile/src/components/agents/attachment-preview-strip.tsx
#	apps/mobile/src/components/agents/markdown-renderer.test.ts
#	apps/mobile/src/components/pr-review/discussion/reaction-picker-sheet.tsx
#	apps/mobile/src/components/pr-review/discussion/reactions-row.tsx
#	apps/mobile/src/components/voice-input-control.tsx
Cut duplicated WCAG helpers, tests that assert test-local arithmetic or
JSX pass-through, and props the composed accessibility label overwrites.
Behavior is unchanged.

- Move the diff-token contrast block next to the palette it paints on, so
  the WCAG math lives in one file.
- Drop the mounting harness around `!useReducedMotion()` and the unread
  `reduceMotion` field.
- Delete duplicate radio, table-row, and reaction-sheet tests.
- Collapse the three-branch chip class names to pairs.
The reaction picker held three refs, a callback guard, a platform branch,
and an `onDismiss` prop to move focus back to one button. The parent owns
the trigger, so it owns the focus restore: one timer, no props.

Prune the mounted suites to the accessibility contract. Assertions on
Tailwind classes, sibling order, element geometry, and JSX pass-through
went out; role, label, state, hidden, and focus assertions stayed.
Comment thread apps/mobile/src/components/pr-review/discussion/reactions-row.tsx Outdated
Reopening the reaction picker inside the restore window let the stale
timer move focus to the trigger behind the sheet. Hold the handle and
clear it on open.

Raise the allowance to 400ms. The slide-out runs ~300ms, so a slow frame
could land the focus call while the Modal is still presented, where it
silently does nothing.
@iscekic
iscekic merged commit 2aefb5e into main Aug 17, 2026
18 checks passed
@iscekic
iscekic deleted the audit-w3c-a11y-semantics-1ab3 branch August 17, 2026 12:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

human-ready The PR is ready for human review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants