Downstream unblock: stacksjs/stx#2089
Craft #373 supplies focus and measurement, but shared non-modal Tooltip/Popover still needs a presentation surface outside clipping ancestors, without replacing live controls or turning the popup into a modal. Craft implementation belongs to the separate Craft agent; no Craft source was changed for this report.
Verified evidence
Inspected Craft main 09a3d61c3334ce033ed418a093d3e17d83b4da6d:
- iOS mutation contract:
insertChildrejects an attached child withNODE_ATTACHED;moveChildrequires the child to already belong to the destination parent, otherwiseNOT_A_CHILD. - Android mutation contract enforces the same restrictions.
removeNoderemoves the entire subtree, so remove/create is not an identity-preserving detach/reattach operation.- iOS child reconciliation looks up retained children under the previous parent and explicitly documents parent-local keys. A full RENDER is therefore not evidence that cross-parent native view identity, drafts, selection, and focus survive.
Minimal topology: root View -> clipped/scrolling owner -> popup View containing a TextInput. Moving the existing popup to the screen overlay layer with insertChild(root, popup) is rejected; moveChild(root, popup) is rejected too. Recreating it is not equivalent for interactive Popover content.
An STX presentation-only portal prototype passed 49 tests because our mock detached/reinserted any child implicitly. We withdrew that prototype and are tightening the mock. This is source-verified contract evidence, not a simulator/device reproduction.
Required outcome (implementation choice belongs to Craft)
Provide an advertised host operation or portal/presentation primitive that can present an existing subtree above clipping/scroll ancestors while preserving its live native identity. An additive atomic reparent operation plus identity-preserving renderer reconciliation is one option; a host-owned presentation layer retaining logical ownership is another.
Please specify:
- Request/event schema and capability flag. Older hosts must fail explicitly rather than silently recreating content.
- Screen-viewport coordinate semantics consistent with View.measure, including safe areas and scrolling. A popup inside a Modal belongs above that modal, not behind it.
- Non-modal hit testing: popup controls work, opening does not trap keyboard/accessibility focus or block the whole screen, and outside touches/back/escape can be handled by the top-layer dismissal policy without also dismissing an underlying modal.
- Stable IDs, handlers, uncontrolled input drafts, caret/selection, and focus across opening, updating, restoring and closing. Prevent cycles and stale/unmounted references atomically.
- Teardown of either the logical owner or presentation target must not leave an orphan visible or release a surviving control accidentally.
Acceptance / coordination
- Maintained iOS and Android tests exercise a popup originating inside a ScrollView/clipped parent, nested-modal stacking, repeated open/close, outside dismissal, and removal while open.
- Pin actual native control identity/state, not only the serialized tree or source strings.
- Report which native platforms were actually run, commit(s), and the released version floor (or explicitly unreleased).
- STX owns shared component behavior, async measurement/placement, logical scope/event/disposal ownership, and adapter integration. Craft owns actual native presentation and identity preservation. No Craft implementation is requested from the STX agent.