Mercurial
view mrjunejune/src/jrpg/index.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 | 41a49c29a28f |
| children |
line wrap: on
line source
<!doctype html> <html lang="en" data-zen-theme="cyberpunk"> <head> <title>Shiba Quest | MrJuneJune</title> {{/parts/base_head.html}} <link rel="preload" href="/public/jrpg/background-frame-2.webp" as="image" media="not ((max-width: 52rem) and (orientation: portrait))"> <link rel="preload" href="/public/jrpg/background-frame-mobile.webp" as="image" media="(max-width: 52rem) and (orientation: portrait)"> <link rel="preload" href="/public/jrpg/bar-ink.webp" as="image"> <link rel="stylesheet" href="/public/mjj-composer.css"> <link rel="stylesheet" href="/public/mjj-modal.css"> <link rel="stylesheet" href="/jrpg/jrpg.css"> <script type="module" src="/public/mjj-composer.js"></script> <script type="module" src="/public/mjj-modal.js"></script> <script type="module" src="/jrpg/jrpg.js"></script> </head> <body class="jrpg-page"> <main class="jrpg-main"> <mjj-jrpg-shell class="jrpg-shell" data-initial-panel="__MJJ_PANEL__" > <div class="jrpg-workspace"> <div class="jrpg-brand"> <header> <h1> <a href="/" data-zen-link-effect="none">MrJuneJune</a> </h1> </header> </div> <nav class="jrpg-frame-controls" aria-label="Window controls"> <zen-button appearance="plain" size="xs"> <button type="button" data-frame-minimize aria-label="Minimize interface" aria-pressed="false" > <zen-icon name="arrow-down"></zen-icon> </button> </zen-button> <zen-button appearance="plain" size="xs"> <button type="button" data-frame-fullscreen aria-label="Toggle fullscreen" aria-pressed="false" > <zen-icon name="external"></zen-icon> </button> </zen-button> <zen-button appearance="plain" size="xs"> <a href="/" aria-label="Close interface and return home"> <zen-icon name="close"></zen-icon> </a> </zen-button> </nav> <mjj-window-modal class="jrpg-mobile-destination-owner" data-mobile-destination-owner > <zen-dialog> <zen-button class="jrpg-mobile-menu-btn" appearance="plain" size="xs"> <button type="button" data-zen-trigger data-mobile-menu-toggle aria-label="Open destination menu" > <zen-icon name="menu"></zen-icon> </button> </zen-button> <dialog class="jrpg-mobile-destination-dialog" data-mobile-destination-dialog > <header class="jrpg-mobile-destination-header" data-modal-header> <zen-button appearance="plain" size="sm" data-mobile-destination-back-owner hidden > <button type="button" data-mobile-destination-back aria-label="Back to destination menu" > <zen-icon name="chevron-left"></zen-icon> Menu </button> </zen-button> <h2 id="jrpg-mobile-destination-title" data-mobile-destination-title data-modal-title >Menu</h2> <zen-button appearance="plain" size="sm"> <button type="button" data-zen-close aria-label="Close destination menu" > <zen-icon name="close"></zen-icon> </button> </zen-button> </header> <zen-scroll-area class="jrpg-mobile-destination-content" data-mobile-destination-content data-modal-body data-cyber-scroll tabindex="0" aria-label="Destination content" ></zen-scroll-area> </dialog> </zen-dialog> </mjj-window-modal> <footer class="jrpg-frame-telemetry" aria-label="System telemetry"> <span aria-label="Temperature unavailable">N/A</span> <span data-frame-account aria-live="polite"><a href="/login?next=/jrpg">LOGIN</a></span> <span data-frame-network aria-label="Status online">ONLINE</span> <time data-frame-uptime aria-label="Uptime">00:00:00</time> </footer> <section class="jrpg-scene" aria-label="Shiba Quest conversation"> <mjj-jrpg-character state="default"> <img data-character alt=""> </mjj-jrpg-character> <mjj-jrpg-chat aria-label="Conversation"> <zen-message-scroller> <div class="jrpg-message-viewport" data-zen-viewport role="log" aria-live="polite" aria-relevant="additions text" > <ol class="jrpg-messages" data-messages></ol> </div> </zen-message-scroller> <nav class="jrpg-turn-navigation" aria-label="Conversation turns"> <zen-button appearance="plain" size="sm"> <button type="button" data-turn-previous aria-label="Previous turn" disabled> <zen-icon name="chevron-left"></zen-icon> Previous </button> </zen-button> <span data-turn-position aria-live="polite">START</span> <zen-button appearance="plain" size="sm"> <button type="button" data-turn-next aria-label="Next turn" disabled> Next <zen-icon name="chevron-right"></zen-icon> </button> </zen-button> </nav> </mjj-jrpg-chat> </section> <section class="jrpg-utility" aria-label="Selected destination"> <mjj-jrpg-preview data-selection="__MJJ_PREVIEW_SELECTION__"> <article class="jrpg-preview-panel" aria-live="polite"> <div class="jrpg-preview-content" data-preview-content __MJJ_PREVIEW_HIDDEN__ > <zen-heading size="xl"> <h2 data-preview-title>__MJJ_PREVIEW_TITLE__</h2> </zen-heading> <p data-preview-copy> __MJJ_PREVIEW_COPY__ </p> <ul class="jrpg-work-showcase" data-work-showcase>__MJJ_PREVIEW_WORKS__</ul> <mjj-content-modal data-detail-modal-owner> <zen-dialog class="jrpg-preview-dialog"> <zen-button appearance="plain" size="xs" data-dialog-trigger-owner hidden> <button type="button" data-zen-trigger tabindex="-1" aria-hidden="true"></button> </zen-button> <dialog class="jrpg-detail-dialog"> <header class="jrpg-dialog-heading" data-modal-header> <div data-modal-heading> <p data-modal-kicker>DESTINATION DATA</p> <h2 id="jrpg-dialog-title" data-dialog-title data-modal-title >Resume</h2> </div> <div class="jrpg-dialog-heading-actions"> <zen-button appearance="plain" size="sm" data-resume-download > <a href="/public/resume.pdf"> Download PDF <zen-icon name="download"></zen-icon> </a> </zen-button> <zen-button appearance="plain" size="sm"> <button type="button" data-zen-close aria-label="Close destination details"> <zen-icon name="close"></zen-icon> </button> </zen-button> </div> </header> <zen-scroll-area class="jrpg-detail-body" data-modal-body data-cyber-scroll tabindex="0" aria-label="Destination details" > <div class="jrpg-detail-content" data-modal-article> <p data-dialog-copy>Experience, projects, and the systems I have helped build.</p> <section class="jrpg-resume-dossier" data-resume-dossier aria-label="Resume dossier" > <p data-resume-status>Loading resume dossier...</p> <div data-resume-content></div> </section> <section class="jrpg-blog-browser" data-blog-browser aria-label="Blog archive" hidden > <aside> <h3>All blogs</h3> <ol data-blog-list> <li>Loading blog archive...</li> </ol> </aside> <article> <p data-blog-status>Select a blog to inspect.</p> <div data-blog-content></div> </article> </section> <section class="jrpg-tool-browser" data-tool-browser aria-label="Tool workspace" hidden > <article> <p data-tool-status>Select a tool to inspect.</p> <div data-tool-content></div> </article> </section> </div> </zen-scroll-area> </dialog> </zen-dialog> </mjj-content-modal> </div> <mjj-conversation-archive __MJJ_ARCHIVE_HIDDEN__ aria-label="Conversations" > <div class="jrpg-archive-heading"> <h2>Archive</h2> <zen-button appearance="plain" size="xs"> <button type="button" data-archive-close aria-label="Close conversations"> <zen-icon name="close"></zen-icon> </button> </zen-button> </div> <div class="jrpg-archive-actions"> <zen-button appearance="plain" size="sm"> <button type="button" data-archive-new> <zen-icon name="plus"></zen-icon> New </button> </zen-button> </div> <ol class="jrpg-archive-list" data-archive-list aria-label="Conversations"> </ol> <zen-button appearance="plain" size="sm" data-archive-load-more-owner hidden> <button type="button" data-archive-load-more>Load more</button> </zen-button> <p class="jrpg-archive-status" data-archive-status aria-live="polite">Loading conversations...</p> <mjj-content-modal data-archive-delete-owner> <zen-dialog> <zen-button appearance="plain" size="xs" hidden> <button type="button" data-zen-trigger tabindex="-1" aria-hidden="true"></button> </zen-button> <dialog class="jrpg-archive-dialog" data-archive-delete-dialog > <header data-modal-header> <h2 id="archive-delete-title" class="jrpg-archive-dialog-title" data-modal-title >Delete this conversation?</h2> </header> <div data-modal-body> <div data-modal-article> <p data-archive-delete-name class="jrpg-archive-dialog-subtitle"></p> </div> </div> <footer class="jrpg-archive-dialog-actions" data-modal-footer> <zen-button appearance="plain" size="md"> <button type="button" data-archive-delete-cancel>Cancel</button> </zen-button> <zen-button appearance="plain" size="md"> <button type="button" data-archive-delete-confirm>Delete</button> </zen-button> </footer> </dialog> </zen-dialog> </mjj-content-modal> <mjj-window-modal data-archive-rename-owner> <zen-dialog> <zen-button appearance="plain" size="xs" hidden> <button type="button" data-zen-trigger tabindex="-1" aria-hidden="true"></button> </zen-button> <dialog class="jrpg-archive-dialog" data-archive-rename-dialog > <header data-modal-header> <h2 id="archive-rename-title" class="jrpg-archive-dialog-title" data-modal-title >Rename conversation</h2> </header> <form id="archive-rename-form" data-modal-body data-archive-rename-form novalidate > <zen-field appearance="plain" size="md"> <label for="archive-rename-input">New title</label> <input id="archive-rename-input" data-archive-rename-input type="text" maxlength="200" required autocomplete="off" > </zen-field> </form> <footer class="jrpg-archive-dialog-actions" data-modal-footer> <zen-button appearance="plain" size="md"> <button type="button" data-archive-rename-cancel>Cancel</button> </zen-button> <zen-button appearance="plain" size="md"> <button type="submit" form="archive-rename-form">Save</button> </zen-button> </footer> </dialog> </zen-dialog> </mjj-window-modal> </mjj-conversation-archive> </article> </mjj-jrpg-preview> </section> <mjj-composer compact> <form class="jrpg-composer" data-composer> <div data-composer-control> <zen-field size="lg"> <label for="jrpg-message" data-composer-label>Message</label> <textarea id="jrpg-message" name="message" rows="3" maxlength="500" placeholder="Ask Epi about this site..." required ></textarea> </zen-field> <div class="jrpg-composer-actions" data-composer-actions> <zen-button size="sm"> <button type="submit" aria-label="Send message"> <span data-composer-action-label>Send</span> <zen-icon name="arrow-right"></zen-icon> </button> </zen-button> <zen-button size="sm" variant="danger" data-composer-cancel-owner hidden > <button type="button" data-composer-cancel aria-label="Cancel response" > <span data-composer-action-label>Cancel</span> <zen-icon name="close"></zen-icon> </button> </zen-button> </div> </div> <p class="jrpg-composer-quota" data-composer-meta data-quota aria-live="polite" hidden ></p> <p class="jrpg-composer-hint" data-composer-meta >Enter to send / Shift + Enter for a new line</p> </form> </mjj-composer> <mjj-jrpg-menu id="jrpg-destination-menu"> <nav aria-label="Shiba Quest destinations"> <p class="jrpg-menu-label">Menu</p> <ul> <li> <zen-button appearance="plain" size="sm"> <button type="button" data-preview="resume" aria-pressed="__MJJ_RESUME_PRESSED__"> <zen-icon name="chevron-right"></zen-icon> Resume </button> </zen-button> </li> <li> <zen-button appearance="plain" size="sm"> <button type="button" data-preview="tools" aria-pressed="__MJJ_TOOLS_PRESSED__"> <zen-icon name="chevron-right"></zen-icon> Tools </button> </zen-button> </li> <li> <zen-button appearance="plain" size="sm"> <button type="button" data-preview="blog" aria-pressed="__MJJ_BLOG_PRESSED__"> <zen-icon name="chevron-right"></zen-icon> Blogs </button> </zen-button> </li> <li> <zen-button appearance="plain" size="sm"> <button type="button" data-preview="conversations" aria-pressed="__MJJ_CONVERSATIONS_PRESSED__"> <zen-icon name="chevron-right"></zen-icon> Conversations </button> </zen-button> </li> </ul> </nav> </mjj-jrpg-menu> <mjj-window-modal class="jrpg-login-dialog-owner" data-login-dialog-owner> <zen-dialog> <zen-button appearance="plain" size="md" hidden> <button type="button" data-zen-trigger tabindex="-1" aria-hidden="true"></button> </zen-button> <dialog class="jrpg-login-dialog" data-login-dialog > <header class="jrpg-login-dialog-header" data-modal-header> <h2 id="jrpg-login-title" data-modal-title>SIGN IN</h2> <zen-button appearance="plain" size="md"> <button type="button" data-zen-close aria-label="Close sign-in dialog"> <zen-icon name="close"></zen-icon> </button> </zen-button> </header> <form id="jrpg-login-form" data-login-form data-modal-body novalidate > <div role="alert" data-login-error aria-live="assertive" hidden></div> <zen-field appearance="plain" size="md"> <label for="jrpg-login-username">Username</label> <input id="jrpg-login-username" name="username" type="text" autocomplete="username" autocapitalize="none" spellcheck="false" required maxlength="32" > </zen-field> <zen-field appearance="plain" size="md"> <label for="jrpg-login-password">Password</label> <input id="jrpg-login-password" name="password" type="password" autocomplete="current-password" required minlength="12" maxlength="1024" > </zen-field> </form> <footer class="jrpg-login-dialog-actions" data-modal-footer> <zen-button appearance="plain" size="md"> <button type="button" data-login-cancel data-zen-close>Cancel</button> </zen-button> <zen-button appearance="plain" size="md"> <button type="submit" form="jrpg-login-form" data-login-submit >Sign in</button> </zen-button> </footer> </dialog> </zen-dialog> </mjj-window-modal> </div> </mjj-jrpg-shell> </main> </body> </html>