diff --git a/apps/cowswap-frontend/src/cow-react/index.tsx b/apps/cowswap-frontend/src/cow-react/index.tsx
index 89d4a1da26..eb78e960c7 100644
--- a/apps/cowswap-frontend/src/cow-react/index.tsx
+++ b/apps/cowswap-frontend/src/cow-react/index.tsx
@@ -9,7 +9,6 @@ import { StrictMode } from 'react'
import { BlockNumberProvider } from '@cowprotocol/common-hooks'
import { isInjectedWidget } from '@cowprotocol/common-utils'
import { nodeRemoveChildFix } from '@cowprotocol/common-utils'
-import { IframeResizer } from '@cowprotocol/common-utils'
import { jotaiStore } from '@cowprotocol/core'
import { SnackbarsWidget } from '@cowprotocol/snackbars'
@@ -80,8 +79,6 @@ root.render(
-
- {isInjectedWidgetMode && }
)
diff --git a/apps/cowswap-frontend/src/modules/injectedWidget/consts.ts b/apps/cowswap-frontend/src/modules/injectedWidget/consts.ts
new file mode 100644
index 0000000000..798cb1bb2a
--- /dev/null
+++ b/apps/cowswap-frontend/src/modules/injectedWidget/consts.ts
@@ -0,0 +1 @@
+export const COW_SWAP_WIDGET_EVENT_KEY = 'cowSwapWidget'
diff --git a/libs/common-utils/src/iframeResizer.ts b/apps/cowswap-frontend/src/modules/injectedWidget/updaters/IframeResizer.ts
similarity index 69%
rename from libs/common-utils/src/iframeResizer.ts
rename to apps/cowswap-frontend/src/modules/injectedWidget/updaters/IframeResizer.ts
index f75abca72d..f9d70003f4 100644
--- a/libs/common-utils/src/iframeResizer.ts
+++ b/apps/cowswap-frontend/src/modules/injectedWidget/updaters/IframeResizer.ts
@@ -1,20 +1,25 @@
import { useEffect, useRef } from 'react'
-const MessageType = {
- IFRAME_HEIGHT: 'iframeHeight',
-}
+import { COW_SWAP_WIDGET_EVENT_KEY } from '../consts'
+import { useInjectedWidgetParams } from '../hooks/useInjectedWidgetParams'
const TARGET_ORIGIN = '*' // Change to CoW specific origin in production
export function IframeResizer() {
+ const { dynamicHeightEnabled } = useInjectedWidgetParams()
const previousHeightRef = useRef(0)
useEffect(() => {
+ if (!dynamicHeightEnabled) return
+
// Initial height calculation and message
const sendHeightUpdate = () => {
const contentHeight = document.body.scrollHeight
if (contentHeight !== previousHeightRef.current) {
- window.parent.postMessage({ type: MessageType.IFRAME_HEIGHT, height: contentHeight }, TARGET_ORIGIN)
+ window.parent.postMessage(
+ { key: COW_SWAP_WIDGET_EVENT_KEY, method: 'iframeHeight', height: contentHeight },
+ TARGET_ORIGIN
+ )
previousHeightRef.current = contentHeight
}
}
@@ -32,7 +37,7 @@ export function IframeResizer() {
return () => {
observer.disconnect()
}
- }, [])
+ }, [dynamicHeightEnabled])
return null
}
diff --git a/apps/cowswap-frontend/src/modules/injectedWidget/updaters/InjectedWidgetUpdater.ts b/apps/cowswap-frontend/src/modules/injectedWidget/updaters/InjectedWidgetUpdater.tsx
similarity index 94%
rename from apps/cowswap-frontend/src/modules/injectedWidget/updaters/InjectedWidgetUpdater.ts
rename to apps/cowswap-frontend/src/modules/injectedWidget/updaters/InjectedWidgetUpdater.tsx
index 54c63dd2a7..5b6dd2d81d 100644
--- a/apps/cowswap-frontend/src/modules/injectedWidget/updaters/InjectedWidgetUpdater.ts
+++ b/apps/cowswap-frontend/src/modules/injectedWidget/updaters/InjectedWidgetUpdater.tsx
@@ -5,11 +5,12 @@ import { deepEqual } from '@cowprotocol/common-utils'
import { useNavigate } from 'react-router-dom'
+import { IframeResizer } from './IframeResizer'
+
+import { COW_SWAP_WIDGET_EVENT_KEY } from '../consts'
import { injectedWidgetMetaDataAtom } from '../state/injectedWidgetMetaDataAtom'
import { injectedWidgetParamsAtom } from '../state/injectedWidgetParamsAtom'
-const COW_SWAP_WIDGET_EVENT_KEY = 'cowSwapWidget'
-
const messagesCache: { [method: string]: unknown } = {}
const getEventMethod = (event: MessageEvent) =>
@@ -88,5 +89,5 @@ export function InjectedWidgetUpdater() {
})
}, [processEvent])
- return null
+ return
}
diff --git a/apps/widget-configurator/src/app/configurator/attachIframeResizer.ts b/apps/widget-configurator/src/app/configurator/attachIframeResizer.ts
deleted file mode 100644
index a0b1ce9d14..0000000000
--- a/apps/widget-configurator/src/app/configurator/attachIframeResizer.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-// TODO: Move this to libs/common-utils/src/iframeResizer.ts as a helper function
-// Adding the file here to avoid TS errors around environment variables
-
-import { useEffect } from 'react'
-
-interface IframeResizerProps {
- iframeId: string
- originCheck?: string
-}
-
-// A utility function to adjust iframe height based on postMessage from iframe content.
-export function AttachIframeResizer({ iframeId, originCheck }: IframeResizerProps) {
- useEffect(() => {
- const iframeElement = document.getElementById(iframeId)
-
- if (!iframeElement) {
- console.error(`No iframe found with ID: ${iframeId}`)
- return
- }
-
- const handleMessage = (event: MessageEvent) => {
- // If an originCheck is provided, validate against it
- if (originCheck && event.origin !== originCheck) return
-
- const data = event.data
-
- // Validate the data format and type before processing it
- if (
- typeof data === 'object' &&
- data.type === 'iframeHeight' &&
- Object.prototype.hasOwnProperty.call(data, 'height')
- ) {
- console.log('got iframeHeight ====>', data.height)
- iframeElement.style.height = 'auto' // Reset the iframe's height
- iframeElement.style.height = `${data.height}px` // Adjust the height based on the content
- }
- }
-
- window.addEventListener('message', handleMessage)
-
- // Cleanup: Remove the event listener when the component is unmounted
- return () => {
- window.removeEventListener('message', handleMessage)
- }
- }, [iframeId, originCheck])
-
- return null
-}
diff --git a/apps/widget-configurator/src/app/configurator/index.tsx b/apps/widget-configurator/src/app/configurator/index.tsx
index 153b3024d2..b5a65f0946 100644
--- a/apps/widget-configurator/src/app/configurator/index.tsx
+++ b/apps/widget-configurator/src/app/configurator/index.tsx
@@ -11,8 +11,10 @@ import {
import WalletIcon from '@mui/icons-material/Wallet'
import LoadingButton from '@mui/lab/LoadingButton'
import Box from '@mui/material/Box'
+import Checkbox from '@mui/material/Checkbox'
import Divider from '@mui/material/Divider'
import Drawer from '@mui/material/Drawer'
+import FormControlLabel from '@mui/material/FormControlLabel'
import Link from '@mui/material/Link'
import Typography from '@mui/material/Typography'
@@ -60,6 +62,8 @@ export function Configurator({ title }: { title: string }) {
const iframeContainerRef = useRef(null)
const updateWidgetRef = useRef(null)
+ const [isDynamicHeightEnabled, setDynamicHeightEnabled] = useState(false)
+
useEffect(() => {
const widgetContainer = iframeContainerRef.current
@@ -84,6 +88,7 @@ export function Configurator({ title }: { title: string }) {
},
},
appParams: {
+ dynamicHeightEnabled: isDynamicHeightEnabled,
enabledTradeTypes,
},
}
@@ -93,7 +98,17 @@ export function Configurator({ title }: { title: string }) {
} else {
updateWidgetRef.current = cowSwapWidget(params, settings)
}
- }, [chainId, enabledTradeTypes, sellToken, sellTokenAmount, buyToken, buyTokenAmount, mode, currentTradeType])
+ }, [
+ chainId,
+ enabledTradeTypes,
+ sellToken,
+ sellTokenAmount,
+ buyToken,
+ buyTokenAmount,
+ mode,
+ currentTradeType,
+ isDynamicHeightEnabled,
+ ])
const handleWidgetRefreshClick = () => {
setMode('light')
@@ -143,6 +158,15 @@ export function Configurator({ title }: { title: string }) {
+ Advanced
+
+ setDynamicHeightEnabled(e.target.checked)} />
+ }
+ label="Dynamic widget height"
+ />
+
{/* } variant="contained" onClick={handleWidgetRefreshClick}>
diff --git a/libs/common-utils/src/index.ts b/libs/common-utils/src/index.ts
index 4a93f2bdbf..ef8fd97326 100644
--- a/libs/common-utils/src/index.ts
+++ b/libs/common-utils/src/index.ts
@@ -52,4 +52,3 @@ export * from './tryParseFractionalAmount'
export * from './maxAmountSpend'
export * from './capitalizeFirstLetter'
export * from './jotai/atomWithPartialUpdate'
-export * from './iframeResizer'
diff --git a/libs/widget-lib/src/cowSwapWidget.ts b/libs/widget-lib/src/cowSwapWidget.ts
index 66e6ad9f04..7f6140bb67 100644
--- a/libs/widget-lib/src/cowSwapWidget.ts
+++ b/libs/widget-lib/src/cowSwapWidget.ts
@@ -19,13 +19,15 @@ export function cowSwapWidget(params: CowSwapWidgetParams, settings: CowSwapWidg
sendMetaData(contentWindow, params.metaData)
+ applyDynamicHeight(iframe, params.height)
+
if (provider) {
const jsonRpcManager = new JsonRpcManager(contentWindow)
jsonRpcManager.onConnect(provider)
}
- return (params: CowSwapWidgetSettings) => updateWidget(params, contentWindow)
+ return (newSettings: CowSwapWidgetSettings) => updateWidget(newSettings, contentWindow, iframe)
}
function createIframe(params: CowSwapWidgetParams, settings: CowSwapWidgetSettings): HTMLIFrameElement {
@@ -41,9 +43,14 @@ function createIframe(params: CowSwapWidgetParams, settings: CowSwapWidgetSettin
return iframe
}
-function updateWidget(params: CowSwapWidgetSettings, contentWindow: Window) {
- const pathname = buildWidgetPath(params.urlParams)
- const search = buildTradeAmountsQuery(params.urlParams).toString()
+function updateWidget(settings: CowSwapWidgetSettings, contentWindow: Window, iframe: HTMLIFrameElement) {
+ const pathname = buildWidgetPath(settings.urlParams)
+ const search = buildTradeAmountsQuery(settings.urlParams).toString()
+
+ // Reset iframe height to default
+ if (!settings.appParams.dynamicHeightEnabled) {
+ iframe.style.height = ''
+ }
contentWindow.postMessage(
{
@@ -53,7 +60,7 @@ function updateWidget(params: CowSwapWidgetSettings, contentWindow: Window) {
pathname,
search,
},
- appParams: params.appParams,
+ appParams: settings.appParams,
},
'*'
)
@@ -75,3 +82,15 @@ function sendMetaData(contentWindow: Window, metaData: CowSwapWidgetMetaData) {
)
})
}
+
+function applyDynamicHeight(iframe: HTMLIFrameElement, defaultHeight: number) {
+ window.addEventListener('message', (event) => {
+ if (event.data.key !== COW_SWAP_WIDGET_EVENT_KEY || event.data.method !== 'iframeHeight') {
+ return
+ }
+
+ const height = event.data.height || defaultHeight
+
+ iframe.style.height = `${height}px`
+ })
+}
diff --git a/libs/widget-lib/src/types.ts b/libs/widget-lib/src/types.ts
index 760dd8e7ba..9dfac7a56a 100644
--- a/libs/widget-lib/src/types.ts
+++ b/libs/widget-lib/src/types.ts
@@ -43,6 +43,7 @@ export interface CowSwapWidgetAppParams {
logoUrl?: string
hideLogo?: boolean
hideNetworkSelector?: boolean
+ dynamicHeightEnabled?: boolean
enabledTradeTypes?: TradeType[]
}