Accessibility
Run the Accessibility Test Framework (ATF) over each rendered preview and surface the findings, the semantic hierarchy, the annotated overlay PNG, and a 48 dp touch-target audit as four related kinds.
At a glance
| Kinds | a11y/atf, a11y/hierarchy, a11y/overlay, a11y/touchTargets |
| Schema version | 1 |
| Modules | :data-a11y-core (published) · :data-a11y-connector · :data-a11y-hierarchy-android |
| Render mode | a11y (daemon-only — opt in via the VS Code chip toggle or compose-preview a11y; standalone composePreviewRender Gradle task does not produce a11y data) |
| Cost | low |
| Token usage | ~100 tok inline (e.g. a11y/atf ~370 chars); +~1.5 k per a11y/overlay PNG read. See token usage. |
| Transport | inline (JSON) · path (overlay PNG) |
| Platforms | Android |
What it answers
a11y/atf— does this preview violate WCAG / Android a11y best practices? EachAccessibilityFindingcarries a check id, severity, source, and the node it implicates. The renderer keepsLocalInspectionMode = falseso Compose populates real semantics; infinite animations tick through rather than parking on the paused frame clock (true regardless of the a11y opt-in).a11y/hierarchy— what does an assistive technology see? Per-nodelabel,role,states,merged,boundsInScreen. Read it the same way TalkBack would.a11y/overlay— the rendered PNG with finding bounding boxes baked in. Pure-image;transport=path.a11y/touchTargets— every interactive node with its measured bounds vs. the 48 dp Material minimum, with overlap detection between adjacent targets.
What it does NOT answer
- It is not a substitute for testing with real assistive technology — TalkBack on a real device may surface gestures or focus order issues that a single static frame can’t.
- It does not opine on copy quality (placeholder text, jargon). Use
text/stringsfor that. - Findings are advisory, not pass/fail; severity is the agent’s signal.
Use cases
- PR review: gate UI PRs on no new
ERROR-severity findings; reviewers can paste the overlay PNG inline. - Refactor confidence: diff
a11y/hierarchybefore/after a state-hoisting change to confirm semantics didn’t regress. - Density audit: sweep all previews for
a11y/touchTargetsviolations on a Wear watch face where small targets matter most.
Payload shape
AccessibilityFindingsPayload, AccessibilityHierarchyPayload,
AccessibilityTouchTargetsPayload, AccessibilityOverlayArtifact
(path-only) — defined in
:data-a11y-core.
// a11y/atf
{
"findings": [
{ "checkId": "TouchTargetSize", "severity": "ERROR",
"label": "Submit", "boundsInScreen": "48,200,144,232" }
]
}
// a11y/hierarchy
{
"nodes": [
{ "label": "Submit", "role": "Button", "states": ["Enabled"],
"merged": true, "boundsInScreen": "48,200,144,232" }
]
}
Enabling
A11y data products are produced exclusively by the preview daemon. There is no Gradle DSL or property knob — opt in per invocation through one of:
- VS Code chip toggle — clicking an
a11y/*chip on a preview card routes a per-previewdata/subscribethrough the daemon. The next render attaches the post-capture walk and stampsa11y-atf.json,a11y-hierarchy.json,a11y-overlay.png, anda11y-touchTargets.jsonunderbuild/compose-previews/data/<id>/. compose-preview a11y— the CLI command spins up a temporary daemon, renders with the a11y subscription on, drains the findings, and shuts down.- MCP / agent flows — the daemon’s
data/subscriberequest enables any subset ofa11y/*kinds for a given preview.
The standalone :composePreviewRenderAll Gradle task does NOT produce a11y
sidecars — it’s a normal-render-only path.
Companion products
- Layout inspector —
compose/semanticsfor testTag / role / mergeMode without the ATF audit. - Strings —
text/stringsfor drawn-text quality next to assistive labels.
See also the agent-facing review guidance in
skills/compose-preview/references/a11y.md.