Focus
Snapshot the Compose focus state of a preview and drive directional
focus traversal (Up, Down, Left, Right, Next, Previous) so
agents can verify keyboard / D-pad navigation without an emulator.
At a glance
| Kind | compose/focus |
| Schema version | 1 |
| Modules | :data-focus-core (published) · :data-focus-connector |
| Render mode | default |
| Cost | low |
| Token usage | Inline JSON, not yet benchmarked. See token usage. |
| Transport | inline |
| Platforms | Android · Desktop · Wear · shared |
What it answers
- Which node holds focus right now? What
testTag, role, label? - After a directional
moveFocus(FocusDirection.Down), where does focus land? - Is there a focus trap, dead end, or unexpected wrap?
- Does the focus ring overlay match the focusable bounds the developer expects?
The connector ships a FocusController that drives Compose’s
FocusManager and a FocusOverlay that renders the focused-node
bounding box on top of the captured PNG.
What it does NOT answer
- It does not test physical input devices (rotary, gamepad, IME hardware) — it operates on the abstract
FocusDirectionenum. - It does not score focus order against a designer-defined intent — it reports what the framework chose; reading whether that’s right is on the reviewer.
Use cases
- TV / Wear traversal: render every
Up/Down/Left/Rightstep from a known starting node and confirm the path lands on the intended target. - Dialog focus restoration: verify focus comes back to the trigger button after a dialog dismisses.
- Form regression: catch a refactor that accidentally makes a
TextFieldnon-focusable.
Override shape
Material3FocusProduct.KIND / FocusOverride and FocusDirection
in :data-focus-core
and daemon:core.
compose/focus is an override capability, not a focused-node snapshot payload. A
renderNow request carries the focus instruction under overrides.focus:
{
"overrides": {
"focus": {
"tabIndex": 1,
"direction": "Down",
"step": 1,
"overlay": true,
"pressed": false
}
}
}
Use compose/semantics to identify the resulting focused node and
its boundsInRoot.
Enabling
Pass an override on renderNow.overrides.focus (MCP) to drive
traversal, or enable the extension and read focused-node snapshots on
every render.
Companion products
- UIAutomator hierarchy —
uia/hierarchyfor the broader set of selector-shaped nodes a click / scroll / type could target. - Layout inspector —
compose/semanticsfor testTag / role / mergeMode of the focused node.