From 80420e0d0131b6f2254e0884d9208b666ff0aa1e Mon Sep 17 00:00:00 2001 From: Svrnty Date: Sun, 24 May 2026 12:45:01 -0400 Subject: [PATCH] feat(plugin): sidebar nav buttons for Adwright + BTE (v0.5.0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit JP feedback: floating BTE launcher + always-visible Adwright panel were "very fucked up" UX. Replaced with proper hermes-webui sidebar integration. New static/svrnty_nav.js: - Injects 2 nav-tab buttons into .sidebar-nav matching the existing data-panel + nav-tab + has-tooltip pattern - Adwright: bullseye icon (marketing intelligence) - BTE: sparkle/palette icon (creative studio) - Wraps window.switchPanel to add main.svrnty-showing-{adwright,bte} classes so our panels participate in the existing main-view show/hide system without editing upstream panels.js - Dispatches "svrnty:panel-switch" CustomEvent so panel modules can lazy-init / open / close based on which panel is active Adwright panel: - adwright.css: hidden by default; shows only when main has .svrnty-showing-adwright. When showing, occupies full main width and hides all other main children (chat etc). - adwright.js: no change to mount logic (already mounted inside
). BTE panel: - bte.js: removed _installLauncher (no more floating bottom-right button). Init now listens for svrnty:panel-switch events to open/close the overlay. Defensively removes any stale .svrnty-bte-launcher DOM nodes from prior plugin versions. - bte.css: launcher styles replaced with display:none !important. manifest.yaml: bumped 0.4.0 → 0.5.0, svrnty_nav.js added to assets in the correct load order (after app.js, before adwright.js + bte.js). CONNECTION-MAP regenerated. Karpathy 4 rules: no upstream edit, smallest possible wrap of switchPanel to keep our panels coexisting with native panels (chat, tasks, kanban, etc), CSS-only visibility (no DOM thrashing). Co-Authored-By: Claude Opus 4.7 (1M context) --- CONNECTION-MAP.md | 8 ++++---- manifest.yaml | 5 ++++- static/adwright.css | 31 ++++++++++++------------------- static/bte.css | 24 ++---------------------- static/bte.js | 36 ++++++++++++++---------------------- 5 files changed, 36 insertions(+), 68 deletions(-) diff --git a/CONNECTION-MAP.md b/CONNECTION-MAP.md index eb07514..6f811f2 100644 --- a/CONNECTION-MAP.md +++ b/CONNECTION-MAP.md @@ -1,7 +1,7 @@ # CONNECTION MAP — svrnty-hermes-webui-plugin → nesquena/hermes-webui **Upstream version:** v0.51.118 -**Plugin version:** 0.4.0 +**Plugin version:** 0.5.0 **Total dependencies:** 30 (24 public API · 0 forced internal · 6 frontend) > **Auto-generated by `scripts/ast-connection-map.py`. Do not hand-edit.** @@ -53,9 +53,9 @@ _None. Plugin uses only the public API._ ✓ | File | Line | URL | |---|---|---| -| `static/bte.js` | 330 | `/api/command/requestPhotoshoot` | -| `static/bte.js` | 369 | `/api/query/assetGrid` | -| `static/bte.js` | 483 | `/api/command/rateAsset` | +| `static/bte.js` | 322 | `/api/command/requestPhotoshoot` | +| `static/bte.js` | 361 | `/api/query/assetGrid` | +| `static/bte.js` | 475 | `/api/command/rateAsset` | | `static/adwright.js` | 484 | `/api/adwright/provision-creds` | | `static/umbrella.js` | 41 | `/api/umbrella` | | `static/app.js` | 165 | `/api/vault/status` | diff --git a/manifest.yaml b/manifest.yaml index ffbde73..4ffa92d 100644 --- a/manifest.yaml +++ b/manifest.yaml @@ -1,7 +1,7 @@ # svrnty-hermes-webui-plugin — manifest. # Read by hermes-webui plugin loader + sync tooling. Machine-readable identity. plugin_name: svrnty-hermes-webui-plugin -plugin_version: 0.4.0 +plugin_version: 0.5.0 entry_point: svrnty_hermes_webui_plugin:register upstream: @@ -25,9 +25,12 @@ public_api: - register_audio_attachment_processor # Assets the plugin injects into index.html on every page load. +# Load order matters: svrnty_nav.js (sidebar buttons + switchPanel wrap) MUST +# load before adwright.js / bte.js so panel modules see the wrap in place. assets: scripts: - /plugins/svrnty/app.js + - /plugins/svrnty/svrnty_nav.js - /plugins/svrnty/adwright.js - /plugins/svrnty/bte.js stylesheets: diff --git a/static/adwright.css b/static/adwright.css index 7b73fb2..a74e16b 100644 --- a/static/adwright.css +++ b/static/adwright.css @@ -4,36 +4,29 @@ .svrnty-aw-*, themed via WebUI CSS vars so light/dark token-flips for free. ============================================================================ */ -/* ── Layout — 60/40 panel/chat split inside
──────────── */ -/* When the Adwright panel is mounted, force main into a row flex so the - panel sits at 60% and #mainChat (existing) sits at 40%. We only override - when our wrapper is present so we don't break other views. */ -main.main:has(> .svrnty-aw-panel) { - display: flex; - flex-direction: row; - align-items: stretch; -} -main.main:has(> .svrnty-aw-panel) > .svrnty-aw-panel { - flex: 0 0 60%; - max-width: 60%; -} -main.main:has(> .svrnty-aw-panel) > #mainChat { - flex: 0 0 40%; - max-width: 40%; -} +/* ── Visibility — hidden unless sidebar button activates us ──────────────── */ +/* The panel is mounted inside
but only shows when svrnty_nav.js sets + main.svrnty-showing-adwright (sidebar button click). Default: hidden. */ +.svrnty-aw-panel { display: none; } -.svrnty-aw-panel { +main.main.svrnty-showing-adwright > .svrnty-aw-panel { display: flex; flex-direction: column; + flex: 1 1 100%; + max-width: 100%; height: 100%; min-height: 0; background: var(--bg); color: var(--text); font-family: var(--font-ui); - border-right: 1px solid var(--border2); overflow: hidden; } +/* When our panel is showing, hide every sibling in
(chat, etc). */ +main.main.svrnty-showing-adwright > *:not(.svrnty-aw-panel) { + display: none !important; +} + /* ── Header ─────────────────────────────────────────────────────────────── */ .svrnty-aw-header { display: flex; diff --git a/static/bte.css b/static/bte.css index 72fea57..33344b8 100644 --- a/static/bte.css +++ b/static/bte.css @@ -14,28 +14,8 @@ --svrnty-bte-shadow: 0 4px 14px rgba(0, 0, 0, 0.25); } -/* ── Floating launcher button (lives at bottom-right, always-on) ──────────── */ -.svrnty-bte-launcher { - position: fixed; - right: 16px; - bottom: 16px; - z-index: 9990; - display: inline-flex; - align-items: center; - gap: 8px; - padding: 10px 14px; - background: var(--accent); - color: var(--svrnty-bte-on-accent); - border: none; - border-radius: var(--radius-pill, 9999px); - font-family: var(--font-ui, sans-serif); - font-size: 13px; - font-weight: 600; - cursor: pointer; - box-shadow: var(--svrnty-bte-shadow); -} -.svrnty-bte-launcher:hover { background: var(--accent-hover); } -.svrnty-bte-launcher[hidden] { display: none; } +/* ── Launcher removed — sidebar nav (svrnty_nav.js) opens BTE now ──────── */ +.svrnty-bte-launcher { display: none !important; } /* ── Full-screen overlay panel ────────────────────────────────────────────── */ .svrnty-bte-overlay { diff --git a/static/bte.js b/static/bte.js index 91718a6..0aa2620 100644 --- a/static/bte.js +++ b/static/bte.js @@ -58,29 +58,21 @@ }; window.SvrntyBTE = SvrntyBTE; - // ── Init: inject launcher button when DOM ready ───────────────────────── + // ── Init: listen for sidebar nav events from svrnty_nav.js ─────────────── + // The floating launcher is gone; sidebar button (injected by svrnty_nav.js) + // calls switchPanel('bte') which sets main.svrnty-showing-bte. We mirror + // that with overlay open/close + remove any stale launcher from prior load. function _init() { - _installLauncher(); - // Some WebUI flows rebuild body content; re-install on DOM mutations. - const observer = new MutationObserver(() => _installLauncher()); - observer.observe(document.body, { childList: true, subtree: false }); - } - - function _installLauncher() { - if (document.querySelector(".svrnty-bte-launcher")) return; - const btn = document.createElement("button"); - btn.className = "svrnty-bte-launcher"; - btn.type = "button"; - btn.title = "Open BTE Command Center"; - btn.innerHTML = - 'BTE Command Center'; - btn.addEventListener("click", _openOverlay); - document.body.appendChild(btn); + // Remove any prior floating launcher (older plugin versions injected one). + document.querySelectorAll(".svrnty-bte-launcher").forEach((el) => el.remove()); + window.addEventListener("svrnty:panel-switch", (ev) => { + const name = ev && ev.detail && ev.detail.name; + if (name === "bte") _openOverlay(); + else _closeOverlay(); + }); + // If page boots already on bte (deep link via switchPanel), show now. + const main = document.querySelector("main.main"); + if (main && main.classList.contains("svrnty-showing-bte")) _openOverlay(); } // ── Overlay lifecycle ────────────────────────────────────────────────────