From ab5364e7143b86f73d9e7d70644075309994ee4d Mon Sep 17 00:00:00 2001 From: isaaclombardssw Date: Thu, 23 Jul 2026 16:23:47 +1000 Subject: [PATCH] =?UTF-8?q?=F0=9F=92=B8=20Mount=20the=20Eventbrite=20Popup?= =?UTF-8?q?=20only=20after=20its=20first=20open?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each Eventbrite CTA mounted a react-responsive-modal instance unconditionally so the close animation could play. On the AI for Business Leaders page that is 8 live modals at first paint. Gate the Popup behind a `hasOpened` flag: nothing mounts until a CTA is clicked, and once opened it stays mounted so the close transition still runs. The script-defer, widget reset, and eventbrite_order_complete conversion tracking are unchanged. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Q8genJyZboXaa4vgYhJF4P --- .../eventbrite/eventbriteModalButton.tsx | 87 ++++++++++--------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/components/eventbrite/eventbriteModalButton.tsx b/components/eventbrite/eventbriteModalButton.tsx index cc0ab24d81..9292326f00 100644 --- a/components/eventbrite/eventbriteModalButton.tsx +++ b/components/eventbrite/eventbriteModalButton.tsx @@ -58,6 +58,8 @@ export const EventbriteModalButton = ({ const reactId = useId().replace(/[^a-zA-Z0-9_-]/g, ""); const containerId = `eventbrite-checkout-${eventId}-${reactId}`; const [open, setOpen] = useState(false); + // Gate the Popup on first open so a closed CTA mounts no react-responsive-modal; once opened it stays mounted for the close animation. + const [hasOpened, setHasOpened] = useState(false); const [scriptLoaded, setScriptLoaded] = useState(false); const [scriptFailed, setScriptFailed] = useState(false); // The popup portals its content, so bind via the callback ref once the node mounts, not when `open` flips. @@ -120,49 +122,54 @@ export const EventbriteModalButton = ({ variant={variant} className={className} textTinaField={textTinaField} - onClick={() => setOpen(true)} + onClick={() => { + setHasOpened(true); + setOpen(true); + }} > {children} - {/* Always mounted (for the close animation); the library unmounts contents while closed, resetting the widget. */} - setOpen(false)} - modalStyle={{ - maxWidth: CHECKOUT_WIDTH_PX, - padding: 0, // padding reads as a white border around the checkout - borderRadius: "0.375rem", // rounded-md, matching the site cards - overflow: "hidden", - background: THEME_SETTINGS.background, - }} - > - {scriptFailed && !scriptLoaded ? ( -
-

The booking form could not be loaded.

- - Register on the Eventbrite event page instead - -
- ) : ( -
- )} - + {/* Mounted only after the first open; stays mounted thereafter so the close animation plays. The library unmounts contents while closed, resetting the widget. */} + {hasOpened && ( + setOpen(false)} + modalStyle={{ + maxWidth: CHECKOUT_WIDTH_PX, + padding: 0, // padding reads as a white border around the checkout + borderRadius: "0.375rem", // rounded-md, matching the site cards + overflow: "hidden", + background: THEME_SETTINGS.background, + }} + > + {scriptFailed && !scriptLoaded ? ( +
+

The booking form could not be loaded.

+ + Register on the Eventbrite event page instead + +
+ ) : ( +
+ )} + + )} ); };