ReviewOS

craft-native/craft

feat(native): expose modal dismissal reasons and view focus/measurement for shared overlays

#373
Closed glennmichael123 opened this 8 days ago ·
8 days ago

Downstream unblock

Required by stacksjs/stx#2089: shared Dialog/Drawer, Tabs, and Tooltip/Popover must use host operations rather than browser DOM APIs or separate native component implementations.

Craft implementation belongs to the agent working in this repository; the STX agent will handle the consuming adapter. No Craft code was changed for this report.

Verified source evidence

Inspected Craft commit af4463007d5b1bec09cd32238e568e83262147c3:

STX cannot enforce independent close-on-backdrop and close-on-back/escape policies from that payload. Its current regression test explicitly denies an ambiguous request when the policies differ, rather than guessing.

Source inspection also has not identified a public bridge operation for focusing or measuring an existing native view by stable node ID. Existing TextInput autoFocus behavior is not an imperative focus/restore API. If an appropriate API already exists, identify its supported contract instead of duplicating it.

Required host contract

  1. Dismissal reason: add an additive nativeEvent.reason to Modal request-close events, distinguishing backdrop, back, and escape wherever supported. Route only to the top visible modal. Preserve controlled dismissal: a denied request must leave the modal visible and interactive; repeated requests must work.
  2. Focus: expose host-backed focus operations addressing a mounted view by stable native node ID. Define keyboard versus accessibility focus, supported targets, modal initial focus, and restoration after close. Unsupported targets and removed nodes must return actionable errors, not silently succeed.
  3. Measurement: expose an asynchronous operation returning a mounted view's viewport-relative bounds and viewport dimensions, with documented units, safe-area/scroll semantics, and validity after layout. This is needed for shared anchored Tooltip/Popover positioning.
  4. Capabilities: advertise actual support and document the request/response contract so STX can detect unsupported versions. Do not require DOM access or app-owned Swift/Kotlin.

Exact API names are for the Craft implementer to choose consistently with existing bridge conventions. Please provide the final schema and version floor for the STX adapter.

Acceptance / maintained tests

  • iOS backdrop and Android backdrop/back report distinct accurate reasons; supported escape paths do too.
  • Nested modals dismiss only the top layer; denied dismissal, reopen, and teardown remain functional.
  • Focus reaches a supported mounted control, does not jump back on unrelated reconciliation, and restoration handles a removed opener safely.
  • Measurement is correct after layout, scrolling, and viewport changes; unmounted IDs reject cleanly.
  • Cover host behavior in the maintained native renderer suites, not only source-string assertions or a JS mock. Report which platforms were actually run.
  • Keep existing consumers compatible with the additive event payload.
  • On completion, record commit(s), maintained test results, and the released Craft version (or explicitly say unreleased).

Coordination

STX owns shared component behavior, overlay stack policy, adapter integration, and same-source tests. Craft owns platform event reasons, actual view focus/measurement, and truthful capability reporting. This issue tracks only the Craft side.

8 days ago

Resolved on main by 95521bf, f1d2368, 1c71095, and 31e22b6. The maintained iOS and Android hosts now report modal dismissal reasons, expose mounted-view focus/measurement with explicit errors and capabilities, and restore focus after modal dismissal. This is on main and unreleased.

Sign in to comment on this issue.