Skip to content

feat: add setAppearance for dark mode and forward custom CSS [ENG-3644] - #64

Open
Dhruwang wants to merge 4 commits into
mainfrom
feat/set-appearance-custom-css
Open

Dhruwang wants to merge 4 commits into
mainfrom
feat/set-appearance-custom-css

Conversation

@Dhruwang

@Dhruwang Dhruwang commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Ref ENG-3644

What & why

Was: iOS surveys always rendered light, and the SDK dropped the workspace's compiled custom CSS.
Now: Formbricks.setAppearance(.light | .dark | .system) switches surveys, live while open. Compiled workspace and survey CSS reach the renderer.

  • setAppearance works before setup, survives logout, resets on app restart, and is never sent to the server. Unknown values log and fall back to light.
  • .system follows the app's own theme (including overrideUserInterfaceStyle), not the phone's.
  • customCss is forwarded untouched, with empty fields omitted and no key when there is none.
  • Fixed a reload: updateUIView called loadHTMLString on every SwiftUI update, which would restart the survey.

Where to look

Coverage

Behaviour Level Evidence
State, unknown value, setup config, logout keeps it, customCss omit/forward/decode unit (mutation) AppearanceTests (new). Rerun: xcodebuild test -scheme FormbricksSDK -destination 'platform=iOS Simulator,name=iPhone 16'
Live light/dark/system switch keeps the typed answer, custom CSS applies, no-overlay mode manual recording and stills below
Overlay (modal) mode manual Not verified, see Open gaps
Screen recording and screenshots

Switching light, dark and system while a survey is open

Full-quality recording (mp4)

Light Dark
Survey in light mode Survey in dark mode with custom CSS

Local Formbricks server on the dark-mode and custom-CSS epic branch, workspace CSS: pill buttons in light, amber buttons in dark. The demo build temporarily allowed http://localhost; that change is not in this PR.

Open gaps

  • Overlay (modal) presentation not run; only no-overlay (passthrough window).
  • .system live updates in the passthrough window rely on the host applying its theme to that window too; the demo sets it on every scene window.
  • A change between the WebView mounting and the survey bundle loading is missed.
  • Needs a server whose renderer has setAppearance; older servers stay light.

Breaking changes

  • None. Purely additive API.

Migrations & env

None. CI: restores the sonarqube-scan-action v6.0.0 pin that #61 bumped to v8.2.2; v8 fails on this runner importing SonarSource's signing key, which broke every SonarQube run on main too.


Agent: claude-sonnet-5-5 (Claude Code), effort unknown.

@CLAassistant

CLAassistant commented Oct 7, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 1c6cbb72-64e9-4c5c-b710-48cac80320a6
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@Dhruwang
Dhruwang requested review from itsjavi and removed request for pandeymangg October 8, 2026 07:06
#61 moved it to v8.2.2, which verifies the scanner's GPG signature against keyservers this
macOS runner cannot reach, so the SonarCloud step fails on every run. Restores the pin the
comment above it describes.
Comment thread Sources/FormbricksSDK/WebView/SurveyWebView.swift
Comment thread Sources/FormbricksSDK/WebView/SurveyWebView.swift Outdated
A setAppearance call made before surveys.umd.cjs finished loading hit no
renderer, yet was recorded as applied, so the survey stayed light and
repeat calls were deduped away. The page now reports onSurveyRendered and
the coordinator holds changes until then, sending the latest one.
…G-3644]

Live syncs read the WebView's traits, but a no-overlay survey lives in the
SDK's own window, which ignores the host window's overrideUserInterfaceStyle.
Resolve from the host window (or presenter) instead, observe it on iOS 17+,
and re-sync on foreground for iOS 16.
@sonarqubecloud

sonarqubecloud Bot commented Oct 8, 2026

Copy link
Copy Markdown

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.

3 participants