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? Each AccessibilityFinding carries a check id, severity, source, and the node it implicates. The renderer keeps LocalInspectionMode = false so 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-node label, 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/strings for 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/hierarchy before/after a state-hoisting change to confirm semantics didn’t regress.
  • Density audit: sweep all previews for a11y/touchTargets violations 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-preview data/subscribe through the daemon. The next render attaches the post-capture walk and stamps a11y-atf.json, a11y-hierarchy.json, a11y-overlay.png, and a11y-touchTargets.json under build/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/subscribe request enables any subset of a11y/* 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 inspectorcompose/semantics for testTag / role / mergeMode without the ATF audit.
  • Stringstext/strings for drawn-text quality next to assistive labels.

See also the agent-facing review guidance in skills/compose-preview/references/a11y.md.


Apache 2.0 licensed. Source on GitHub.

This site uses Just the Docs, a documentation theme for Jekyll.