Skip to content

fix: let host-app touches through when the survey has no overlay [ENG-3156] - #81

Merged
Dhruwang merged 2 commits into
mainfrom
anshuman/eng-3156-react-native-sdk-host-app-takes-no-touches-while-any-survey
Oct 1, 2026
Merged

Dhruwang merged 2 commits into
mainfrom
anshuman/eng-3156-react-native-sdk-host-app-takes-no-touches-while-any-survey

Conversation

@pandeymangg

@pandeymangg pandeymangg commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Ref ENG-3156

Depends on formbricks/formbricks#9242 being deployed; until then the SDK keeps taking every touch. Native counterparts: formbricks/ios#57, formbricks/android#87.

What & why

Was: every survey rendered in a transparent <Modal>, which takes every touch however see-through it is, so the host app was frozen until the survey closed. none is the default overlay.

Now: with overlay: none, only the survey card takes touches; everything else reaches the host app. Light and dark overlays still block, as before.

Where to look

  • components/utils/survey-touch-region.ts: the three card states and the clip geometry.
  • components/survey-web-view.tsx: the no-overlay render path, keyboard handling and CloseOnBack.
  • lib/survey/action.ts: the new "already showing" guard.
How it works, and behaviour changes worth checking

For overlay: none the WebView renders in the host's own view tree instead of a Modal. It stays full-size (so the renderer lays the card out exactly as before) inside a view clipped to the rect the renderer reports; React Native hit-testing respects that clip. Resizing the WebView to the card does not work: the renderer caps the card at 60dvh of the WebView's own viewport, so the two shrink each other to a clipped height.

  • Back closes a no-overlay survey (the Modal's onRequestClose did this before). Passing it to the host could navigate away and leave the survey over another screen.
  • A second survey no longer replaces the open one. The host is usable mid-survey, so it can track again; triggerSurvey now skips while a survey is showing.
  • Keyboard. iOS keeps KeyboardAvoidingView. On Android it left a nav-bar gap after the keyboard closed, so Android pads by however much of the survey's area the keyboard covers; an app that already resizes for the keyboard gets none.
  • <Formbricks />'s wrapper now fills its parent, since a no-overlay survey positions itself against it. Rendering it at the app root, as the README shows, is unchanged.
  • A host Modal opened while the survey is up covers it; one already open when the survey triggers hides it until it closes.

Coverage

Behaviour Level
overlay: none: host usable beside the card, card inside, nothing left after close (iOS + Android) manual: iPhone/iPad simulators, Android emulator, Expo 55, local formbricks/formbricks#9242 web
Portrait/landscape, center placement, keyboard on both platforms, back on Android manual
overlay: light: Modal path unchanged, host blocked; after Android back the next trigger shows manual
No rect yet blocks everything; junk is not read as "no card" unit (mutation): survey-touch-region.ts:69 drop card === undefined, :33 junk → null
Clip geometry per state; keyboard padding; bridge wired into renderSurvey unit (guard): survey-touch-region.test.ts, survey-web-view-harness.test.ts
A second survey does not replace the open one unit (mutation): action.ts:26 guard off

Rerun: pnpm --filter @formbricks/react-native test

Open gaps

  • Simulators and emulator only; no physical device.
  • Tested in Expo Go against a local SDK build, not a bare React Native app.
  • Android keyboard checked edge-to-edge only; an adjustResize app without edge-to-edge is untested.

Breaking changes

  • This PR contains a breaking change

No public API change.

@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: e8bfd3ac-281c-4c0f-9baf-62a373fe6eef

📥 Commits

Reviewing files that changed from the base of the PR and between 3824bad and 6d80374.

📒 Files selected for processing (7)
  • packages/react-native/src/components/formbricks.tsx
  • packages/react-native/src/components/survey-web-view.tsx
  • packages/react-native/src/components/tests/survey-touch-region.test.ts
  • packages/react-native/src/components/tests/survey-web-view-harness.test.ts
  • packages/react-native/src/components/utils/survey-touch-region.ts
  • packages/react-native/src/lib/survey/action.ts
  • packages/react-native/src/lib/survey/tests/action.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


Walkthrough

No-overlay surveys now render in the host view tree and use the renderer-reported card rectangle to define the touch region. Android keyboard padding and hardware-back handling are added for this path; overlay surveys continue to use a modal. The Formbricks wrapper fills its parent. Survey triggers now skip replacing a survey that is already showing.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 6d803

The changes are mergeable after normal checks. Touch passthrough still depends on deployment of the compatible renderer; older renderers retain the documented full-area fallback.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 6d803

The change has bounded client-side exposure and retains existing navigation and message controls. However, dismissing an overlay survey with Android back can now leave an invisible survey registered and block later surveys. Native touch behavior and renderer compatibility also require validation.

Retained concerns

  • Medium · reliability · observed: Android back dismissal of a light or dark overlay hides the Modal without clearing SurveyStore. The new already-showing guard then rejects subsequent survey triggers even though no survey is visible. This turns a pre-existing cleanup omission into a cross-component ownership and recovery failure; ordinary later triggers no longer recover by replacing the stored survey.
Security review details

Security Blast Radius

  • inferred — The demonstrated new authority is client-side control of survey clipping and touch routing within the host presentation area. Source does not establish increased tenant, backend, credential, or data-store authority. The trigger recovery failure affects subsequent surveys sharing the singleton store in that SDK runtime.

Security Findings and Attack Paths

  • inferred — Code executing in the WebView can submit numeric geometry that native code applies without nonnegative or host-bound constraints. This establishes a new geometry authority edge, not a verified security regression: the former Modal already intercepted all touches, and geometry messages cannot invoke other bridge effects. Out-of-bounds native hit-testing behavior remains unverified.

Trust Boundaries and Controls

  • observed — The renderer-to-native boundary validates geometry shape but trusts its coordinates. Missing reports conservatively retain full-area blocking; invalid reports are ignored. Existing payload escaping prevents survey JSON from breaking out of the generated inline script, and URL restrictions remain separate from geometry processing.

Resilience and Maintainability Implications

  • inferred — The new guard makes store ownership an admission-control invariant rather than merely a rendering input. Every terminal path must therefore release ownership consistently; the overlay-back exception strands admission closed. This is a bounded recovery concern, not evidence of privilege escalation or data exposure.

Hardening Proposals

  • proposed — Consider defining native-side geometry bounds and normalization against the measured host area, then validating clipping and hit-testing across supported native versions. This would constrain renderer authority explicitly; it is hardening, not a verified vulnerability fix.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 7 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the main change: allowing host-app touches outside surveys without an overlay.
Description check ✅ Passed The description accurately explains the no-overlay touch behavior, related changes, testing coverage, dependencies, and known gaps.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@pandeymangg
pandeymangg requested review from Dhruwang and mattinannt and removed request for mattinannt September 30, 2026 14:43

@Dhruwang Dhruwang left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two findings from a correctness pass: one confirmed, one plausible.

Comment thread packages/react-native/src/lib/survey/action.ts
Comment thread packages/react-native/src/components/survey-web-view.tsx Outdated
@sonarqubecloud

sonarqubecloud Bot commented Oct 1, 2026

Copy link
Copy Markdown

@pandeymangg
pandeymangg requested a review from Dhruwang October 1, 2026 10:09
@Dhruwang
Dhruwang added this pull request to the merge queue Oct 1, 2026
Merged via the queue into main with commit ad32210 Oct 1, 2026
10 checks passed
@Dhruwang
Dhruwang deleted the anshuman/eng-3156-react-native-sdk-host-app-takes-no-touches-while-any-survey branch October 1, 2026 10:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants