← back to AbramsOS
chat: move Model/Agent pickers to a centered top-middle nav bar; panel drops from it (was a corner bubble) (TK-11084)
ee61b912e8892319eb1dc5b3f76b82f1a2883427 · 2026-09-01 17:57:19 -0700 · Steve
Files touched
M public/css/app.cssM public/js/chat.jsM views/partials/chat.ejsM views/partials/header.ejs
Diff
commit ee61b912e8892319eb1dc5b3f76b82f1a2883427
Author: Steve <steve@designerwallcoverings.com>
Date: Tue Sep 1 17:57:19 2026 -0700
chat: move Model/Agent pickers to a centered top-middle nav bar; panel drops from it (was a corner bubble) (TK-11084)
---
public/css/app.css | 30 ++++++++++++++++++++++++++++--
public/js/chat.js | 2 ++
views/partials/chat.ejs | 31 ++++++-------------------------
views/partials/header.ejs | 19 +++++++++++++++++++
4 files changed, 55 insertions(+), 27 deletions(-)
diff --git a/public/css/app.css b/public/css/app.css
index ad98325..d721bf4 100644
--- a/public/css/app.css
+++ b/public/css/app.css
@@ -428,9 +428,35 @@ html.nav-collapsed .side-actions { flex-direction: column; }
}
.aos-chat-launcher:hover { background: var(--surface-strong); }
+/* Top-middle chat nav bar (the Model/Agent pickers live here) */
+.aos-topbar {
+ position: sticky; top: 0; z-index: 42;
+ margin: 0 0 14px; padding: 8px 12px;
+ border: 1px solid var(--border);
+ display: flex; justify-content: center;
+}
+.aos-topbar-inner {
+ display: flex; align-items: center; gap: 10px; flex-wrap: wrap; justify-content: center;
+ width: 100%; max-width: 900px;
+}
+.aos-tb-field { display: inline-flex; align-items: center; gap: 6px; }
+.aos-tb-label { font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--text-dim); }
+.aos-topbar select {
+ background: var(--surface-strong); color: var(--text);
+ border: 1px solid var(--border); border-radius: var(--radius-sm);
+ padding: 6px 8px; font-size: 13px; max-width: 220px;
+}
+.aos-tb-ask {
+ background: var(--surface-strong); color: var(--text);
+ border: 1px solid var(--border-strong); border-radius: 999px;
+ cursor: pointer; padding: 6px 14px; font-size: 13px; font-weight: 600;
+}
+.aos-tb-ask:hover { filter: brightness(1.1); }
+.aos-chat-title { font-size: 13px; }
+
.aos-chat-panel {
- position: fixed; right: 20px; bottom: 84px; z-index: 41;
- width: 420px; max-width: calc(100vw - 32px);
+ position: fixed; top: 60px; left: 50%; transform: translateX(-50%); z-index: 41;
+ width: 460px; max-width: calc(100vw - 32px);
height: 560px; max-height: calc(100vh - 120px);
display: flex; flex-direction: column; overflow: hidden;
padding: 0;
diff --git a/public/js/chat.js b/public/js/chat.js
index af6085a..1ee22cf 100644
--- a/public/js/chat.js
+++ b/public/js/chat.js
@@ -89,6 +89,7 @@
}
function showSpec(kind) {
+ panel.hidden = false; // triggered from the top-bar ⓘ — make sure the panel is open
rosterEl.hidden = true;
specEl.hidden = false;
specEl.innerHTML = '';
@@ -97,6 +98,7 @@
}
function toggleAllSpecs() {
+ panel.hidden = false; // triggered from the top-bar "All specs" — open the panel
specEl.hidden = true;
if (!rosterEl.hidden) { rosterEl.hidden = true; return; }
rosterEl.hidden = false;
diff --git a/views/partials/chat.ejs b/views/partials/chat.ejs
index 5a8cd2d..175f98a 100644
--- a/views/partials/chat.ejs
+++ b/views/partials/chat.ejs
@@ -1,30 +1,11 @@
-<!-- Nav-bar chat: model + agent pickers, spec cards, chat panel. Rendered on
- every page via footer.ejs. Dynamic roster comes from /api/chat/registry. -->
-<button id="aosChatLauncher" class="aos-chat-launcher glass" aria-label="Open chat" title="Chat">💬</button>
-
+<!-- Nav-bar chat PANEL. The Model/Agent pickers + lane badge + "All specs" +
+ "💬 Ask" launcher live in the TOP BAR (views/partials/header.ejs, top-middle).
+ This is just the conversation drop-down the top bar opens. Rendered on every
+ page via footer.ejs. Roster/specs come from /api/chat/registry. -->
<section id="aosChatPanel" class="aos-chat-panel glass" hidden aria-label="AbramsOS chat">
<header class="aos-chat-head">
- <div class="aos-chat-pickers">
- <label class="aos-chat-field">
- <span>Model</span>
- <span class="aos-chat-selwrap">
- <select id="aosChatModel"></select>
- <button type="button" class="aos-chat-info" data-spec="model" title="Model spec">ⓘ</button>
- </span>
- </label>
- <label class="aos-chat-field">
- <span>Agent</span>
- <span class="aos-chat-selwrap">
- <select id="aosChatAgent"></select>
- <button type="button" class="aos-chat-info" data-spec="agent" title="Agent spec">ⓘ</button>
- </span>
- </label>
- </div>
- <div class="aos-chat-head-right">
- <span id="aosChatLane" class="aos-chat-lane" title="Where your data goes"></span>
- <button type="button" id="aosChatAllSpecs" class="aos-chat-allspecs" title="All specs">All specs</button>
- <button type="button" id="aosChatClose" class="aos-chat-close" aria-label="Close">✕</button>
- </div>
+ <strong class="aos-chat-title">Assistant</strong>
+ <button type="button" id="aosChatClose" class="aos-chat-close" aria-label="Close">✕</button>
</header>
<div id="aosChatSpec" class="aos-chat-spec" hidden></div>
diff --git a/views/partials/header.ejs b/views/partials/header.ejs
index dfa6be4..c2e2814 100644
--- a/views/partials/header.ejs
+++ b/views/partials/header.ejs
@@ -78,4 +78,23 @@
</script>
</aside>
<div class="content-wrap">
+ <% if (typeof userId !== 'undefined' && userId) { %>
+ <div class="aos-topbar glass">
+ <div class="aos-topbar-inner">
+ <span class="aos-tb-field">
+ <span class="aos-tb-label">Model</span>
+ <select id="aosChatModel"></select>
+ <button type="button" class="aos-chat-info" data-spec="model" title="Model spec">ⓘ</button>
+ </span>
+ <span class="aos-tb-field">
+ <span class="aos-tb-label">Agent</span>
+ <select id="aosChatAgent"></select>
+ <button type="button" class="aos-chat-info" data-spec="agent" title="Agent spec">ⓘ</button>
+ </span>
+ <span id="aosChatLane" class="aos-chat-lane" title="Where your data goes"></span>
+ <button type="button" id="aosChatAllSpecs" class="aos-chat-allspecs" title="All specs">All specs</button>
+ <button type="button" id="aosChatLauncher" class="aos-tb-ask">💬 Ask</button>
+ </div>
+ </div>
+ <% } %>
<main>
← 8205414 chat: drop dead Gemini models from picker (Google prepay $0)
·
back to AbramsOS
·
chat: guard registry+chat fetch against creds-in-URL (resolv cf095c7 →