fix(site-builder): entrance-animation reveal script survives Preview + well-formed void-tag attrs + no-JS fallback

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-14 12:12:01 -07:00
co-authored by Claude Opus 4.8
parent 4e0fc78a30
commit 2dcc2b4d21
3 changed files with 195 additions and 7 deletions
+13 -3
View File
@@ -133,7 +133,7 @@ export const TopBar: React.FC<TopBarProps> = ({ device, onDeviceChange, showGuid
const handlePreview = useCallback(() => {
try {
const serialized = query.serialize();
import('../../utils/html-export').then(({ exportToHtml, exportBodyHtml }) => {
import('../../utils/html-export').then(({ exportToHtml, exportBodyHtml, buildAnimationScript }) => {
// Get header HTML
let headerHtml = '';
try {
@@ -154,8 +154,18 @@ export const TopBar: React.FC<TopBarProps> = ({ device, onDeviceChange, showGuid
}
} catch (e) { console.warn('Footer export failed:', e); }
// Compose full page: header + body + footer
const composedBody = headerHtml + bodyHtml + footerHtml;
// Compose full page: header + body + footer. `handlePreview` below
// replaces the ENTIRE wrapped-doc `<body>` inner (including the
// in-body reveal `<script>` wrapInDocument already emitted) with
// this composed string, so the script would otherwise be clobbered
// and animated elements would stay hidden forever
// ([data-animation]{opacity:0} with no IntersectionObserver to ever
// add `.animated`). Re-append the reveal script here -- built from
// the SAME composed content it will end up living alongside -- so
// it survives the replacement below and fires exactly once.
const composedBody =
headerHtml + bodyHtml + footerHtml +
buildAnimationScript(headerHtml + bodyHtml + footerHtml);
// PKG-H: fold the active page's own SEO overrides + the site-wide
// design tokens/favicon into the Preview export so editor Preview