Mercurial
view 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 source
<!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><mjj-content-modal> <header data-modal-header>...</header> <zen-scroll-area data-modal-body data-cyber-scroll> ... </zen-scroll-area> <footer data-modal-footer>...</footer> </mjj-content-modal></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>