From de68699fa6c5c98d1c742cfb39e5b3e715ace28d Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 22 Sep 2026 20:47:15 +0000 Subject: [PATCH] fix: Use the form background behind the fullscreen mobile popup On phones the popup fills the viewport and iOS Safari paints the status bar and bottom toolbar from the fixed container's own background, so the dark scrim shows up as grey bands around the form. Set a CSS custom property from the form-theme message (as the widget fullscreen modal already does) and consume it only inside the mobile media query, keeping the dark scrim on desktop and until the theme arrives. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01RkM7Yh51Sqg4iADSZnyJXL --- packages/embed/src/css/popup.scss | 1 + .../create-popup/create-popup.spec.ts | 20 +++++++++++++++++++ .../factories/create-popup/create-popup.ts | 12 +++++++++++ 3 files changed, 33 insertions(+) diff --git a/packages/embed/src/css/popup.scss b/packages/embed/src/css/popup.scss index e78a865f..45f42a81 100644 --- a/packages/embed/src/css/popup.scss +++ b/packages/embed/src/css/popup.scss @@ -34,6 +34,7 @@ @include mobile { .tf-v1-popup { @include fullsize; + background: var(--tf-popup-background, rgba(0, 0, 0, 0.75)); .tf-v1-iframe-wrapper { position: relative; diff --git a/packages/embed/src/factories/create-popup/create-popup.spec.ts b/packages/embed/src/factories/create-popup/create-popup.spec.ts index f6353629..cd5ca04f 100644 --- a/packages/embed/src/factories/create-popup/create-popup.spec.ts +++ b/packages/embed/src/factories/create-popup/create-popup.spec.ts @@ -41,6 +41,26 @@ describe('create-popup', () => { expect(wrapper.style.width).toBe('200px') expect(wrapper.style.height).toBe('100px') }) + + it('should set the popup background from the form theme', () => { + const popupElement = container.querySelector('.tf-v1-popup') as HTMLElement + const iframe = popupElement.querySelector('iframe') as HTMLIFrameElement + const embedId = new URL(iframe.src).searchParams.get('typeform-embed-id') + + window.dispatchEvent( + new MessageEvent('message', { + data: { type: 'form-theme', embedId: 'other-embed-id', theme: { backgroundColor: 'rgba(0, 0, 255, 0)' } }, + }) + ) + expect(popupElement.style.getPropertyValue('--tf-popup-background')).toBe('') + + window.dispatchEvent( + new MessageEvent('message', { + data: { type: 'form-theme', embedId, theme: { backgroundColor: 'rgba(255, 200, 0, 0)' } }, + }) + ) + expect(popupElement.style.getPropertyValue('--tf-popup-background')).toBe('rgba(255, 200, 0, 255)') + }) }) describe('#close', () => { diff --git a/packages/embed/src/factories/create-popup/create-popup.ts b/packages/embed/src/factories/create-popup/create-popup.ts index 17b5b90e..707b6d2b 100644 --- a/packages/embed/src/factories/create-popup/create-popup.ts +++ b/packages/embed/src/factories/create-popup/create-popup.ts @@ -10,8 +10,10 @@ import { invokeWithoutDefault, handlePreventReopenOnClose, closeIconSvg, + changeColorOpacity, } from '../../utils' import type { RemoveHandler } from '../../utils' +import { getFormThemeHandler } from '../../utils/create-iframe/get-form-event-handler' import { POPUP_SIZE } from '../../constants' import { isInPage, isOpen } from '../../utils' import { EmbedPopup } from '../../base' @@ -84,6 +86,16 @@ export const createPopup = (formId: string, userOptions: PopupOptions = {}): Pop popup.append(spinner) popup.append(wrapper) + window.addEventListener( + 'message', + getFormThemeHandler(embedId, (data) => { + const backgroundColor = data?.theme?.backgroundColor + if (backgroundColor) { + popup.style.setProperty('--tf-popup-background', changeColorOpacity(backgroundColor)) + } + }) + ) + const container = options.container || document.body iframe.onload = (event) => {