Layout inspector
The Compose layout / component hierarchy with bounds, constraints,
modifiers, and source refs — plus a sibling compose/semantics
projection for testTag / role / mergeMode questions.
At a glance
| Kinds | layout/inspector, compose/semantics |
| Schema version | 1 |
| Modules | :data-layoutinspector-core (published) · :data-layoutinspector-connector |
| Render mode | default |
| Cost | low |
| Token usage | Inline JSON, not yet benchmarked (scales with hierarchy depth). See token usage. |
| Transport | inline |
| Platforms | Android · Desktop · shared |
What it answers
layout/inspector— what’s the parent / child shape of this composable? Measured size? Constraints? Z-order? Which inspectable modifiers are attached, with what values? Which source file / line declared the node?compose/semantics— for eachSemanticsNode, what is itstestTag,role,mergeMode,bounds?
It is intentionally separate from a11y/hierarchy — the
question there is “what does an assistive technology see”; the
question here is layout structure or stable test selectors.
What it does NOT answer
- It does not run accessibility checks — that is
a11y/atf. - It does not measure recomposition — that is
compose/recomposition. - The Desktop / shared backend reaches the layout tree through
RootForTest; non-Compose Android views (interop) are not modelled.
Use cases
- Pinpoint which composable owns a misaligned region from
history/diff/regions. - Confirm a refactor preserved testTags so existing UI tests keep finding their targets.
- Inspect resolved
Modifier.padding(...)values when a screenshot says one thing and the source says another. - Drive the VS Code extension’s tree view of a preview.
Payload shape
LayoutInspectorPayload, LayoutInspectorNode,
ComposeSemanticsPayload, ComposeSemanticsNode in
:data-layoutinspector-core.
// layout/inspector
{
"nodes": [
{ "nodeId": "1", "component": "Column",
"bounds": { "left": 0, "top": 0, "right": 1080, "bottom": 1920 },
"measuredSize": "1080x1920",
"constraints": "minW=0, maxW=1080, minH=0, maxH=1920",
"modifiers": [{ "name": "padding", "args": "16dp" }],
"sourceRef": "HomeScreen.kt:42" }
]
}
// compose/semantics
{
"nodes": [
{ "nodeId": "2", "testTag": "submit-button", "role": "Button",
"mergeMode": "mergeDescendants", "boundsInRoot": "48,200,144,232" }
]
}
Enabling
Producer runs whenever its owning extension is publicly enabled.
Backed on Android by the daemon’s RootForTest carried on
PreviewContext.inspection. CLI / Gradle output:
build/compose-previews/data/<id>/layout-inspector.json and
compose-semantics.json.
The compose-preview serve viewer projects the same tree into three
inspection layers over the rendered frame — Overlays → Inspect →
Typography (per text node: resolved size / line height / face / weight,
from ComposeSemanticsNode.typography), Theme attributes (per
container: resolved fill or gradient, border, corner radius, shape, shadow
elevation, effective alpha and clip, from ComposeSemanticsNode.tokens,
anchored to the node’s captured paintBox when it has one) and Layout
boxes (per slot: the box’s own size and origin, its per-edge padding, the
arrangement gap and any defaultMinSize floor). The compact legend row
carries what fits on one line; the row’s tooltip carries the whole resolved
token map. All three are served by /render/<id>.annotations as
DesignAnnotations, the same shape the design-comparison page draws its
producer-authored spec layers from — so the Layout layer is the code-side
counterpart of the reference-side layout redline, and quotes the same tokens
as the published layout wireframe.
Companion products
- Accessibility —
a11y/hierarchyfor the assistive-technology view of the same nodes. - Recomposition —
compose/recompositionfor per-node recomposition counts keyed off the same node ids. - Theme —
compose/themefor the tokens consumed at each node.