Skip to content

fix: adds click outside close and overlay settings#38

Merged
pandeymangg merged 3 commits intomainfrom
fix/click-outside-close-ios
Feb 11, 2026
Merged

fix: adds click outside close and overlay settings#38
pandeymangg merged 3 commits intomainfrom
fix/click-outside-close-ios

Conversation

@pandeymangg
Copy link
Contributor

What does this PR do?

Implements the iOS SDK counterpart to formbricks/formbricks#7197, which replaces the darkOverlay boolean with a new overlay enum (none, light, dark) and fixes clickOutsideClose not being passed to the survey JS library.

Fixes #37

Changes

New SurveyOverlay enum (Survey.swift)

  • Added SurveyOverlay enum with cases none, light, dark, matching the backend's SurveyOverlay schema.

Model updates (Project.swift, Survey.swift)

  • Project.darkOverlay: Bool?Project.overlay: SurveyOverlay?
  • ProjectOverwrites.darkOverlay: Bool?ProjectOverwrites.overlay: SurveyOverlay?

Native overlay background (PresentSurveyManager.swift)

  • The modal background color was previously hardcoded to UIColor.gray.withAlphaComponent(0.6) regardless of config. It now respects the resolved overlay value:
    • dark → dark semi-transparent background
    • light → light semi-transparent background
    • none → fully transparent (clear)
  • present() now accepts an overlay parameter, resolved by SurveyManager.

Overlay resolution (SurveyManager.swift)

  • Added resolveOverlay(for:) helper that follows the correct precedence: survey-level projectOverwrites.overlay → project-level overlay.none.
  • Both track() and showSurvey() resolve and pass the overlay to the presenter.

WebView data (FormbricksViewModel.swift)

  • Replaced data["darkOverlay"] (Bool) with data["overlay"] (String: "none" / "light" / "dark"), matching the JS survey library's expected prop.
  • Bug fix: Added data["clickOutside"], which was missing entirely. Without it, the JS survey library's click-outside-to-dismiss handler never activated, even when clickOutsideClose was true.

Test updates (FormbricksSDKTests.swift, Environment.json)

  • Updated mock JSON: "darkOverlay": false"overlay": "none", "darkOverlay": true"overlay": "dark".
  • Updated WebView data assertions to verify overlay as a string and clickOutside as a boolean.

How should this be tested?

  • Create a survey with overlay set to Dark → verify the native modal shows a dark semi-transparent background and the JS overlay renders dark
  • Create a survey with overlay set to Light → verify a lighter background
  • Create a survey with overlay set to None → verify a fully transparent background
  • Enable clickOutsideClose with a light or dark overlay → verify tapping outside the survey card dismisses it
  • Disable clickOutsideClose → verify tapping outside does nothing
  • Verify survey-level projectOverwrites.overlay overrides the project-level default
  • Verify backward compatibility: surveys without an overlay field default to none

@pandeymangg pandeymangg requested a review from Dhruwang February 10, 2026 10:47
@coderabbitai
Copy link

coderabbitai bot commented Feb 10, 2026

Walkthrough

This change refactors the overlay system by replacing a boolean darkOverlay property with a SurveyOverlay enum containing three cases: none, light, and dark. The enum is introduced in the Survey model and propagated across the codebase. The Project struct and ProjectOverwrites properties are updated to use the new enum type. The PresentSurveyManager adds an overlay parameter to its present() method with a helper function to map overlay values to specific background colors. The SurveyManager introduces a resolveOverlay() helper that determines the appropriate overlay based on survey-specific overwrites or project defaults, and passes this value through the presentation flow. Test expectations and mock data are updated accordingly to reflect the new enum-based structure.

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: introducing click outside close and overlay settings, which are the primary features added in this PR.
Description check ✅ Passed The description comprehensively explains the changes, rationale, and testing approach, all related directly to the changeset.
Linked Issues check ✅ Passed The PR successfully implements support for closable overlays by replacing darkOverlay boolean with SurveyOverlay enum, fixing clickOutsideClose data passing, and implementing proper overlay resolution with survey-level precedence.
Out of Scope Changes check ✅ Passed All changes directly address the linked issue requirements: overlay enum implementation, modal background adaptation, clickOutsideClose fix, and proper precedence handling across managers and models.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
Sources/FormbricksSDK/WebView/FormbricksViewModel.swift (1)

111-111: Qualify SurveyOverlay.none to avoid ambiguity with Optional.none.

While Swift resolves .none correctly here (the ?? operator requires a non-optional SurveyOverlay on the right-hand side), the bare .none is a well-known readability trap when working with optionals of types that also have a .none case. Explicitly qualifying it prevents confusion for future readers.

Suggested change
-        data["overlay"] = (matchedSurvey?.projectOverwrites?.overlay ?? project.overlay ?? .none).rawValue
+        data["overlay"] = (matchedSurvey?.projectOverwrites?.overlay ?? project.overlay ?? SurveyOverlay.none).rawValue
Sources/FormbricksSDK/Model/Environment/Survey.swift (1)

38-43: Consider the naming collision between SurveyOverlay.none and Optional.none.

The none case shadows Optional.none, which can cause ambiguity at call sites when working with SurveyOverlay?. This is already observable in the ViewModel code. If renaming is feasible (e.g., .noOverlay), it would eliminate the ambiguity entirely. If not (e.g., the raw value "none" must match the backend), the current approach works but requires care at usage sites.

Sources/FormbricksSDK/Manager/SurveyManager.swift (1)

350-357: Overlay resolution logic is duplicated with FormbricksViewModel.

resolveOverlay(for:) implements the same precedence chain (survey.projectOverwrites.overlay → project.overlay → .none) as the inline expression in FormbricksViewModel (Line 111). They serve different consumers (native background vs. JS payload), but if the precedence rules ever change, both must be updated in sync. Consider extracting a shared static helper if this becomes a maintenance concern.

Also, same .none / Optional.none ambiguity note applies on Line 356 — qualifying as SurveyOverlay.none would be clearer.


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 and usage tips.

@sonarqubecloud
Copy link

@pandeymangg pandeymangg added this pull request to the merge queue Feb 11, 2026
Merged via the queue into main with commit b613764 Feb 11, 2026
4 checks passed
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.

Add support for closable overlays

2 participants