Skip to content

Name the enlarged chat image for VoiceOver - #6262

Merged
BunsDev merged 1 commit into
mainfrom
fix/issue-5314-zoomed-image-a11y-label
Oct 26, 2026
Merged

BunsDev merged 1 commit into
mainfrom
fix/issue-5314-zoomed-image-a11y-label

Conversation

@BunsDev

@BunsDev BunsDev commented Oct 26, 2026

Copy link
Copy Markdown
Member

Refs #5314 (task T2). The issue stays open for the physical-device capture and the VoiceOver and copy/share pass.

What

The native zoom view rendered the enlarged image with no accessibility label. On main, the zoom cover's accessibility tree shows the enlarged image as Image, {{0.0, 317.3}, {402.0, 301.3}} with no label or identifier, so VoiceOver announces a bare "image". Inline markdown images already carry alt text in the WebView (the fixture's ![Zoom fixture image A](…) is labelled there), but the enlarge bridge dropped it.

Change

  • apps/ios/markdown/entry.mjs: the enlarge message also carries the tapped <img>'s alt.
  • MarkdownWebView.swift: handleEnlarge reads alt, and presentImage(src:alt:fallbackHTML:) passes it to ContentZoom.image(_:description:).
  • ContentZoom.swift: ZoomTarget.Content.image gains an optional description. ZoomTarget.imageAccessibilityLabel(description:) returns the trimmed description, or "Enlarged image" when there is none (attachments, or images with empty alt text). ZoomableImageView applies that label and a Zoomed image identifier. No hint was added: the design language doesn't call for one, and pinch or double-tap hints would mislead VoiceOver users (see the note below).
  • The bounded cache and downsampling path from fix(ios): bound inline image zoom and cancel stale presentations #5482/Add a repeatable iOS image zoom performance driver #5768 is unchanged.

Tests

  • ContentZoomTests: label from a description (trimmed), the fallback for nil/blank, and ContentZoom.image(_:description:) keeping the description.
  • MarkdownWebViewLifecycleTests.testInlineImageZoomKeepsItsAltTextForVoiceOver: an enlarge script message with alt produces a zoom target carrying it.
  • PerformanceBaselineUITests.testZoomedImageIsNamedByItsAltText: opens the image-zoom fixture, taps image A, and asserts the enlarged image's accessibility label is Zoom fixture image A.
  • scripts/ios-accessible-controls.test.mjs: pins the bridge's alt field and the view's label and identifier, because CI compiles UI tests but doesn't run them.

Verification

  • The new UI test fails on the unmodified app at the enlarged-image assertion. It passes with this change.
  • xcodebuild test, scheme CovenCave, iPhone 17 simulator, CODE_SIGNING_ALLOWED=NO, run on ContentZoomTests, MarkdownWebViewLifecycleTests and CaveImageCacheTests: 45 tests, 0 failures. All four new unit tests ran.
  • xcodebuild test, scheme CovenCavePerformance (Release), same simulator: testZoomedImageIsNamedByItsAltText passed, and testImageZoomCycles passed all 100 cycles.
  • pnpm test:mobile (106 files), pnpm check:tests-wired, and node --test scripts/ios-accessible-controls.test.mjs (4/4) pass.

Note for the VoiceOver pass (T6): the zoom gestures (pinch, drag, double-tap at count: 2) have no accessibility actions, so VoiceOver users can read the image but probably can't zoom it. That is out of scope here and worth checking on device.

The native zoom view rendered the enlarged image with no accessibility
label, so VoiceOver landed on a bare "image". Inline markdown images
already carry alt text in the WebView, but the enlarge bridge dropped it.

Send the tapped image's alt text with the enlarge message, carry it on
the image zoom target, and label the zoomed image with it. Images with
no description, such as attachments, are named "Enlarged image".

Cover the label rule and the bridge in the unit bundle, add a UI test
that opens the zoom fixture and checks the enlarged image's name, and
pin the bridge field and label in the accessible-controls source test.

Refs #5314
@github-project-automation github-project-automation Bot moved this to Todo in Cave Oct 26, 2026
@BunsDev
BunsDev merged commit 8601670 into main Oct 26, 2026
24 checks passed
@BunsDev
BunsDev deleted the fix/issue-5314-zoomed-image-a11y-label branch October 26, 2026 20:45
@github-project-automation github-project-automation Bot moved this from Todo to Done in Cave Oct 26, 2026
BunsDev added a commit that referenced this pull request Oct 26, 2026
## Summary
- Stamp v0.5.18 across `package.json`, `tauri.conf.json`, `Cargo.toml`, `Cargo.lock` and the iOS `project.yml` (marketing version 0.5.18, build `2026102622`).
- Curate the notes for the changes since v0.5.17: the Next.js and DOMPurify security updates (#6267, #6264), local-model checks on every launch path (#6263), Coven history metadata export (#6255), the VoiceOver label for enlarged chat images (#6262), and maintenance (#6254, #6253, #6256, #6260).
- State plainly that Cave doesn't enable the Next.js features the advisories target, rather than overstating exposure.
- Disclose again that the Windows MSI is not Authenticode-signed in this cut.

Refs #6270

## Verification
- `node scripts/stamp-release.mjs --prepare-only --level patch --allow-version-gap`, from the managed `release/stamp-v0.5.18` worktree at live `origin/main` `a95e34d0a`. There is no gap: `GET /releases/latest` returns `v0.5.17` (GraphQL was rate-limited), and the continuity check below passes.
- `pnpm release:verify --version 0.5.18`: five manifests and the final changelog agree.
- `pnpm release:verify-continuity --published 0.5.17`: 0.5.17 → 0.5.18.
- `src/lib/app-version.test.ts` and `scripts/stamp-release.test.mjs` pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant