Render live content in accessibility previews#340
Draft
RoyalPineapple wants to merge 3 commits into
Draft
Conversation
- Extract a shared makeSwiftUIHostingController helper in FBSnapshotTestCase+SwiftUI and SnapshotTesting+SwiftUI. On iOS 16.4+ it uses safeAreaRegions = []; on earlier iOS it wraps the rootView in .ignoresSafeArea() so the same alignment guarantee holds across all supported iOS versions. - Add HierarchyColorAssignmentTests covering the invariant that an element's colorIndex equals its position in flattenToElements(), plus container indices being sequential and independent of elements. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The parser already assigns each element a sequential `traversalIndex` that equals its position in `flattenToElements()` (the markers array). There's no need for a separate type to "build" a sort-and-map between them — they're the same number. Replace HierarchyColorAssignment + its parallel AssignedNode tree + the build() dance with a small private helper inside HierarchyLegendView: - Element colorIndex comes straight from traversalIndex - Container colorIndex is a simple depth-first counter HierarchyLegendView now takes [AccessibilityHierarchy] directly. Drop HierarchyColorAssignment.swift (public type) and HierarchyColorAssignmentTests (the invariant is now a passthrough of the parser's contract, already covered upstream). Net: -159 lines, one fewer public type, one fewer file. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`.accessibilityPreview()` previously captured a UIImage of the content and overlaid markers on that snapshot. The image capture produced an empty image in the off-screen window because SwiftUI's render server doesn't reliably commit there. Embed the content directly in a ZStack and overlay parsed marker shapes on top — spinners spin, counters tick, async loads update. Markers are still parsed once on appear via the existing off-screen hosting controller (needed for window-relative accessibilityFrame coordinates), and their shapes are positioned in the same coordinate space as the displayed content because both render at renderSize. Also adds the hierarchical container legend to the live-preview path when configuration.showContainers is true, matching the snapshot-test behavior. If the content layout changes after parse — e.g. a text label grows — the overlay frames stay at the parse-time geometry; a refresh hook is left as a follow-up. Snapshot-test path is unaffected: it still uses PreParsedAccessibility- SnapshotView and captures pixels via SwiftUIAccessibilitySnapshot- ContainerView. This change only touches AccessibilitySnapshotView, the live-preview type. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3170c21 to
cf266b9
Compare
3e1b99a to
5cf916a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
.accessibilityPreview()now embeds the previewed content live in a ZStack instead of capturing a static UIImage of it. Spinners spin, counters tick, async loads update — anything stateful keeps running.HierarchyLegendView) to the live-preview path whenconfiguration.showContainersis true, matching the snapshot-test behavior.Scope
Only touches
AccessibilitySnapshotView(the live-preview type). The snapshot-test path (PreParsedAccessibilitySnapshotView,SwiftUIAccessibilitySnapshotContainerView) is unaffected and continues to capture pixels through the same flow.Tradeoff
Markers are parsed once on appear. If the previewed content's layout changes after parse (e.g. a text label widens), the overlay frame stays at the parse-time geometry. A
refresh()hook or layout-change-driven re-parse is a reasonable follow-up.Stack
Based on
a11y-container-graph(#278). Merge that first.Test plan
BasicAccessibilityDemo().accessibilityPreview()as the root — confirm overlays sit over the live demo contentconfiguration: .init(viewRenderingMode: .drawHierarchyInRect, showContainers: true)and a container demo — confirm hierarchical legend renders belowProgressViewinside a previewed view continues to animate🤖 Generated with Claude Code