diff mrjunejune/src/public/component-sandbox.html @ 273:e02e2036ef84 default tip

add Layer 2 JRPG component system Add reusable content and window modals, an isolated component sandbox, shared cyberpunk scroll areas, production-safe cache freshness, and server-rendered JRPG panel state. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Sat, 08 Aug 2026 02:08:08 -0700
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrjunejune/src/public/component-sandbox.html	Sat Aug 08 02:08:08 2026 -0700
@@ -0,0 +1,263 @@
+<!doctype html>
+<html lang="en" data-zen-theme="cyberpunk">
+  <head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>AI Component Sandbox | MrJuneJune</title>
+    <link rel="stylesheet" href="/public/design-system/styles/tokens.css">
+    <link rel="stylesheet" href="/public/design-system/styles/themes.css">
+    <link rel="stylesheet" href="/public/design-system/styles/components.css">
+    <script type="module" src="/public/design-system/components/index.js"></script>
+    <script type="module">
+      const version = Date.now();
+      const styles = [
+        "/public/mjj-modal.css",
+        "/public/component-sandbox.css",
+      ];
+      await Promise.all(styles.map(href => new Promise((resolve, reject) => {
+        const link = document.createElement("link");
+        link.rel = "stylesheet";
+        link.href = `${href}?sandbox=${version}`;
+        link.addEventListener("load", resolve, { once: true });
+        link.addEventListener("error", reject, { once: true });
+        document.head.append(link);
+      })));
+      await import(`/public/mjj-modal.js?sandbox=${version}`);
+      void navigator.serviceWorker?.getRegistration()
+        .then(registration => registration?.update());
+    </script>
+  </head>
+  <body>
+    <main>
+      <header class="sandbox-heading">
+        <p class="sandbox-muted">Isolated browser fixture</p>
+        <h1>AI Component Sandbox</h1>
+        <p>
+          Edit one component family, refresh this page, and inspect desktop or
+          mobile behavior without application chrome.
+        </p>
+        <dl class="sandbox-layers" aria-label="Component dependency layers">
+          <div>
+            <dt>Layer 0 · Foundation</dt>
+            <dd>API mapping, i18n, and semantic themes.</dd>
+          </div>
+          <div>
+            <dt>Layer 1 · Primitives</dt>
+            <dd>Zenbu icons, fields, buttons, and dialog behavior.</dd>
+          </div>
+          <div>
+            <dt>Layer 2 · Composites</dt>
+            <dd>MrJuneJune composers and modal families.</dd>
+          </div>
+        </dl>
+        <p class="sandbox-rule">
+          Dependency rule: Layer 2 may consume Layers 1 and 0. Application
+          routes, persistence, and business state stay above this sandbox.
+        </p>
+      </header>
+
+      <section class="sandbox-grid" aria-label="Modal component variants">
+        <article class="sandbox-card">
+          <h2>Content modal</h2>
+          <p>
+            Editorial reading surface for blogs, notes, release details, and
+            long-form content.
+          </p>
+          <mjj-content-modal data-component-layer="2">
+            <zen-dialog>
+              <zen-button size="md">
+                <button type="button" data-zen-trigger>
+                  Open article
+                  <zen-icon name="external"></zen-icon>
+                </button>
+              </zen-button>
+              <dialog>
+                <header data-modal-header>
+                  <div data-modal-heading>
+                    <p data-modal-kicker>Engineering note · 8 min read</p>
+                    <h2 data-modal-title>Designing durable agent interfaces</h2>
+                  </div>
+                  <div data-modal-header-actions>
+                    <zen-button variant="quiet" size="sm">
+                      <button type="button" data-zen-close aria-label="Close article">
+                        <zen-icon name="close"></zen-icon>
+                      </button>
+                    </zen-button>
+                  </div>
+                </header>
+                <zen-scroll-area
+                  data-modal-body
+                  data-cyber-scroll
+                  tabindex="0"
+                  aria-label="Article content"
+                >
+                  <article data-modal-article>
+                    <p data-modal-description>
+                      A content modal should feel like a focused reading room:
+                      enough structure to orient the reader, but no window chrome
+                      competing with the article.
+                    </p>
+                    <h2>Start with a strict shell</h2>
+                    <p>
+                      Header, body, and footer are stable regions. The article
+                      owns its semantic headings, paragraphs, lists, and code.
+                      The modal only supplies rhythm, containment, scrolling,
+                      and depth.
+                    </p>
+                    <blockquote>
+                      Content should remain ordinary HTML even when the
+                      presentation becomes cinematic.
+                    </blockquote>
+                    <h3>Keep the body readable</h3>
+                    <p>
+                      The reading column stays bounded while the dialog itself
+                      can grow. This avoids very long lines on desktop and keeps
+                      padding deliberate on small screens.
+                    </p>
+                    <h3>Use a visible scroll channel</h3>
+                    <p>
+                      Cyan marks the active rail, violet separates the track,
+                      and magenta appears on hover. Keyboard users can focus the
+                      region and scroll without moving the modal chrome.
+                    </p>
+                    <p>
+                      The header and footer stay fixed while this article moves.
+                      That stable frame keeps context visible during longer blog
+                      posts, documentation, and generated explanations.
+                    </p>
+                    <p>
+                      Layer 2 only chooses layout and presentation. The Layer 1
+                      scroll primitive still owns the native overflow behavior.
+                    </p>
+                    <pre><code>&lt;mjj-content-modal&gt;
+  &lt;header data-modal-header&gt;...&lt;/header&gt;
+  &lt;zen-scroll-area data-modal-body data-cyber-scroll&gt;
+    ...
+  &lt;/zen-scroll-area&gt;
+  &lt;footer data-modal-footer&gt;...&lt;/footer&gt;
+&lt;/mjj-content-modal&gt;</code></pre>
+                  </article>
+                </zen-scroll-area>
+                <footer data-modal-footer>
+                  <p>Updated August 7, 2026</p>
+                  <div data-modal-footer-actions>
+                    <zen-button variant="quiet" size="md">
+                      <button type="button" data-zen-close>Done reading</button>
+                    </zen-button>
+                  </div>
+                </footer>
+              </dialog>
+            </zen-dialog>
+          </mjj-content-modal>
+        </article>
+
+        <article class="sandbox-card">
+          <h2>Window modal</h2>
+          <p>
+            Structured workspace for tools and multi-region interfaces with
+            fixed chrome and a bounded scrolling body.
+          </p>
+          <mjj-window-modal data-component-layer="2">
+            <zen-dialog>
+              <zen-button size="md">
+                <button type="button" data-zen-trigger>
+                  Open workspace
+                  <zen-icon name="external"></zen-icon>
+                </button>
+              </zen-button>
+              <dialog>
+                <header data-modal-header>
+                  <div data-modal-heading>
+                    <p data-modal-kicker>Workspace · Read only</p>
+                    <h2 data-modal-title>Component inspector</h2>
+                  </div>
+                  <div data-modal-header-actions>
+                    <zen-button variant="quiet" size="sm">
+                      <button type="button" aria-label="Component settings">
+                        <zen-icon name="settings"></zen-icon>
+                      </button>
+                    </zen-button>
+                    <zen-button variant="quiet" size="sm">
+                      <button type="button" data-zen-close aria-label="Close workspace">
+                        <zen-icon name="close"></zen-icon>
+                      </button>
+                    </zen-button>
+                  </div>
+                </header>
+                <zen-scroll-area
+                  data-modal-body
+                  data-modal-layout="split"
+                  data-cyber-scroll
+                  tabindex="0"
+                  aria-label="Workspace content"
+                >
+                  <zen-scroll-area
+                    data-modal-pane
+                    data-cyber-scroll
+                    tabindex="0"
+                    aria-label="Inspector regions"
+                  >
+                    <aside class="sandbox-pane">
+                      <h3>Regions</h3>
+                      <ul class="sandbox-list">
+                        <li>Header</li>
+                        <li>Body</li>
+                        <li>Footer</li>
+                      </ul>
+                    </aside>
+                  </zen-scroll-area>
+                  <zen-scroll-area
+                    data-modal-pane="primary"
+                    data-cyber-scroll
+                    tabindex="0"
+                    aria-label="Inspector body content"
+                  >
+                    <article class="sandbox-pane">
+                      <h3>Body content</h3>
+                      <p data-modal-description>
+                        The window body can host split panes, editors, previews,
+                        or tools without changing the surrounding contract.
+                      </p>
+                      <zen-field size="md">
+                        <label for="sandbox-component-name">Component name</label>
+                        <input
+                          id="sandbox-component-name"
+                          value="mjj-window-modal"
+                          readonly
+                        >
+                        <small>The active light-DOM fixture.</small>
+                      </zen-field>
+                      <ol class="sandbox-audit">
+                        <li><strong>01</strong> Header region validated</li>
+                        <li><strong>02</strong> Title association generated</li>
+                        <li><strong>03</strong> Body region bounded</li>
+                        <li><strong>04</strong> Scroll primitive connected</li>
+                        <li><strong>05</strong> Footer actions discovered</li>
+                        <li><strong>06</strong> Pixel typography inherited</li>
+                        <li><strong>07</strong> Cyberpunk theme resolved</li>
+                        <li><strong>08</strong> Keyboard scrolling enabled</li>
+                        <li><strong>09</strong> Responsive split verified</li>
+                        <li><strong>10</strong> Layer contract ready</li>
+                      </ol>
+                    </article>
+                  </zen-scroll-area>
+                </zen-scroll-area>
+                <footer data-modal-footer>
+                  <p>3 required regions · contract valid</p>
+                  <div data-modal-footer-actions>
+                    <zen-button variant="quiet" size="md">
+                      <button type="button" data-zen-close>Cancel</button>
+                    </zen-button>
+                    <zen-button size="md">
+                      <button type="button" data-zen-close>Apply</button>
+                    </zen-button>
+                  </div>
+                </footer>
+              </dialog>
+            </zen-dialog>
+          </mjj-window-modal>
+        </article>
+      </section>
+    </main>
+  </body>
+</html>