fix: resolve nested HTML documents causing LiveView binding errors

The shop.html.heex and shop_root.html.heex were both full HTML documents.
When nested (root layout + live layout), this created invalid HTML with
duplicate <!DOCTYPE>, <html>, <head>, and <body> tags.

This caused:
- "Cannot bind multiple views to the same DOM element" console errors
- Failed Lighthouse audits
- Potential rendering issues

Fix:
- shop_root.html.heex: Now contains the full HTML document with theme
  settings, CSS variables, and data attributes
- shop.html.heex: Now just passes through @inner_content

Results:
- Console errors: Gone
- Best Practices: 96 → 100
- Total Blocking Time: 140ms → 30ms
- HTML validation: Passes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jamey Greenwood 2026-01-21 20:20:39 +00:00
parent 5faa6c4c09
commit f29772010e
2 changed files with 19 additions and 35 deletions

View File

@ -1,31 +1 @@
<!DOCTYPE html>
<html lang="en" class="h-full">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="csrf-token" content={get_csrf_token()} />
<.live_title><%= assigns[:page_title] || @theme_settings.site_name %></.live_title>
<link phx-track-static rel="stylesheet" href={~p"/assets/css/app.css"} />
<script defer phx-track-static type="text/javascript" src={~p"/assets/js/app.js"}>
</script>
<!-- Generated theme CSS (only active values, not all variants) -->
<style id="theme-css"><%= Phoenix.HTML.raw(@generated_css) %></style>
</head>
<body class="h-full">
<div
class="themed shop-root h-full"
data-mood={@theme_settings.mood}
data-typography={@theme_settings.typography}
data-shape={@theme_settings.shape}
data-density={@theme_settings.density}
data-grid={@theme_settings.grid_columns}
data-header={@theme_settings.header_layout}
data-sticky={to_string(@theme_settings.sticky_header)}
data-layout={@theme_settings.layout_width}
data-shadow={@theme_settings.card_shadow}
data-button-style={@theme_settings.button_style}
>
<%= @inner_content %>
</div>
</body>
</html>

View File

@ -4,14 +4,28 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="csrf-token" content={get_csrf_token()} />
<.live_title default="SimpleshopTheme">
{assigns[:page_title]}
</.live_title>
<.live_title><%= assigns[:page_title] || @theme_settings.site_name %></.live_title>
<link phx-track-static rel="stylesheet" href={~p"/assets/css/app.css"} />
<script defer phx-track-static type="text/javascript" src={~p"/assets/js/app.js"}>
</script>
<!-- Generated theme CSS (only active values, not all variants) -->
<style id="theme-css"><%= Phoenix.HTML.raw(@generated_css) %></style>
</head>
<body class="h-full">
<div
class="themed shop-root h-full"
data-mood={@theme_settings.mood}
data-typography={@theme_settings.typography}
data-shape={@theme_settings.shape}
data-density={@theme_settings.density}
data-grid={@theme_settings.grid_columns}
data-header={@theme_settings.header_layout}
data-sticky={to_string(@theme_settings.sticky_header)}
data-layout={@theme_settings.layout_width}
data-shadow={@theme_settings.card_shadow}
data-button-style={@theme_settings.button_style}
>
{@inner_content}
</div>
</body>
</html>