Repository navigation
Conversation
Shadowed composes the content twice, the second time as the shadow, and that copy kept its semantics. Compose leaves out an accessibility node where a sibling drawn above it covers it, so the copy surfaced wherever the shadow extends past the content: with an offset, TalkBack found the label twice and an unlabelled click target under each button. Clear the copy's semantics.
Ceylo
marked this pull request as ready for review
October 2, 2026 17:16
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.
What
Shadowedcomposes the content twice, the second time as the shadow, and that copy kept its semantics. Compose drops a node that a sibling above it fully covers, so a plain.shadow(radius:)hid the copy. But wherever the shadow extends past the content, the copy reached TalkBack: with an offset, a second copy of a shadowed label and an unlabelled click target under a shadowed button. This PR clears the copy's semantics withclearAndSetSemantics {}.Before / after
Accessibility nodes from
uiautomator dump, outlined on the screenshot (Fuse, API 37 emulator); red marks nodes that exist only before. Two rows added locally to the Shadow playground:Text("Shifted")and a borderedButton("Press"), each with.shadow(color: .black, radius: 4, x: 0, y: 12).In the Shadow playground as shipped, the shadowed
Togglealso loses an 11 px unlabelled click target beside its switch.Side effects
Verified
swift test: 118 Swift tests, 55 skipped, 0 failures. JUnit: 162 tests, 157 passed, 5 skipped.main'sShadowed.kt, both new tests fail withExpected exactly '1' node but found '2'(one on the label, one on the click action); with this branch they pass.Skip Pull Request Checklist:
swift testWritten with Claude Code: the fix, the tests and this description. Every claim above comes from a run: the mutation run, and the Showcase in Lite and Fuse on an emulator before and after, with node counts from the accessibility dump and a pixel comparison of the Shadow playground.