Skip to content

Add accessibility modifiers#59

Merged
colemancda merged 5 commits into
masterfrom
feature/accessibility
Jul 24, 2026
Merged

Add accessibility modifiers#59
colemancda merged 5 commits into
masterfrom
feature/accessibility

Conversation

@colemancda

Copy link
Copy Markdown
Member

.accessibilityLabel, .accessibilityValue, .accessibilityHidden, .accessibilityAddTraits, and .accessibilityIdentifier — the last Tier-A system, and the one that was blocking shipping a real app.

Shape

These describe a view rather than changing it, so all of them fold into Compose semantics and nothing else: label → contentDescription, value → stateDescription, traits → Role.Button/Role.Image/heading()/selected, identifier → testTag. Hiding uses clearAndSetSemantics, which drops the node and its subtree — the right meaning for a container.

Verified against the real accessibility tree

Accessibility is unusually verifiable here: uiautomator reads the accessibility tree directly, so this is ground truth rather than pixel inspection.

  • labelText("7").accessibilityLabel("Unread messages") reports content-desc="Unread messages". The label replaces the underlying text, which is the whole point.
  • hidden — the hidden view appears 0 times in the tree while its sibling appears once. It's genuinely gone, not just visually suppressed.
  • traits.isButton changes the node's class from android.widget.TextView to android.widget.Button; a neighbouring untagged Text stays a TextView as a control.

swift test covers emission for all of them (101 passing), including that accessibilityHidden(false) still emits — it has to be able to override an inherited hide — and that adding a description leaves the node type, children, and text untouched.

What I could not verify, and why

accessibilityValue (stateDescription), the .isHeader trait, and .accessibilityIdentifier (testTag) are all applied, but uiautomator's XML has no attribute for any of them — its node schema is a fixed set that excludes state description, heading, and test tags (the last needs testTagsAsResourceId). TalkBack and Compose UI tests read them; this harness can't. I'd rather flag that than imply I confirmed it.

Deliberately not included

.accessibilityElement(children:). I implemented it, and semantics(mergeDescendants = true) did not merge the children — the two texts stayed separate nodes in the tree. Rather than ship a modifier that silently does nothing, I removed it. (That failure mode is exactly the unread-detents bug from #58, so shipping it would have been the same mistake.) .accessibilityHint is also absent: Compose semantics has no hint equivalent, and faking it by appending to the label would corrupt what gets announced.

@colemancda
colemancda merged commit 4cdc464 into master Jul 24, 2026
6 checks passed
@colemancda
colemancda deleted the feature/accessibility branch July 24, 2026 03:25
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.

1 participant