Skip to content

feat(ios): add VoiceOver element tree for rendered markdown - #655

Merged
maksg merged 1 commit into
mainfrom
ios-parity/06-voiceover
Aug 13, 2026
Merged

feat(ios): add VoiceOver element tree for rendered markdown#655
maksg merged 1 commit into
mainfrom
ios-parity/06-voiceover

Conversation

@maksg

@maksg maksg commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Matches the Android package's TalkBack virtual view hierarchy. The rendered attributed string is segmented into per-element VoiceOver nodes: paragraphs split on newlines with spacer lines dropped, and heading, link, and image runs carved into their own elements with plain text between them.

Headings carry the header trait plus the heading-level text attribute ("heading, level N"), links activate the onLinkPress handler via accessibilityActivate, images read their alt text, and list items announce their position ("bullet point", "list item N", with a "nested" prefix) exactly like Android. A list item's extent is the intersection of its number and depth attribute runs, since either alone merges with a neighbor.

Element frames resolve lazily from TextKit 2 layout on every query, so scrolling and Dynamic Type changes never leave stale bounds. Requires iOS 16 (frame math goes through textLayoutManager); iOS 15 keeps the stock single-element behavior.

What/Why?

Testing

PR Checklist

  • Code compiles and runs on iOS
  • Code compiles and runs on Android
  • Updated documentation/README if applicable
  • Ran example app to verify changes
  • E2E tests are passing
  • Required E2E tests have been added (if applicable)

@maksg
maksg force-pushed the ios-parity/05-local-images-downsampling branch from 2c665e6 to 943a03a Compare August 13, 2026 10:35
Base automatically changed from ios-parity/05-local-images-downsampling to main August 13, 2026 11:07
Matches the Android package's TalkBack virtual view hierarchy. The
rendered attributed string is segmented into per-element VoiceOver
nodes: paragraphs split on newlines with spacer lines dropped, and
heading, link, and image runs carved into their own elements with
plain text between them.

Headings carry the header trait plus the heading-level text attribute
("heading, level N"), links activate the onLinkPress handler via
accessibilityActivate, images read their alt text, and list items
announce their position ("bullet point", "list item N", with a
"nested" prefix) exactly like Android. A list item's extent is the
intersection of its number and depth attribute runs, since either
alone merges with a neighbor.

Element frames resolve lazily from TextKit 2 layout on every query, so
scrolling and Dynamic Type changes never leave stale bounds. Requires
iOS 16 (frame math goes through textLayoutManager); iOS 15 keeps the
stock single-element behavior.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@maksg
maksg force-pushed the ios-parity/06-voiceover branch from 2fa2ef1 to fe5adb1 Compare August 13, 2026 11:07
@maksg
maksg merged commit 52e386c into main Aug 13, 2026
9 checks passed
@maksg
maksg deleted the ios-parity/06-voiceover branch August 13, 2026 11:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants