mirror of
https://github.com/turnstonelabs/turnstone.git
synced 2026-08-28 06:44:51 -06:00
fix: remove hamburger menu and logout button from server UI header (#256)
Replace with a direct theme toggle button matching the console UI pattern. Dashboard remains accessible via Ctrl+D.
This commit is contained in:
+21
-99
@@ -2151,101 +2151,34 @@ window.onLogout = function () {
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
// 7. Theme + hamburger menu
|
||||
// 7. Theme toggle
|
||||
// ===========================================================================
|
||||
|
||||
function updateThemeMenuItem() {
|
||||
var isLight = document.documentElement.dataset.theme === "light";
|
||||
document.getElementById("theme-menu-icon").textContent = isLight
|
||||
? "\u263E"
|
||||
: "\u2600";
|
||||
document.getElementById("theme-menu-label").textContent = isLight
|
||||
? "Dark mode"
|
||||
: "Light mode";
|
||||
document
|
||||
.getElementById("theme-menu-item")
|
||||
.setAttribute(
|
||||
window.onThemeChange = function (next) {
|
||||
var btn = document.getElementById("theme-toggle");
|
||||
if (btn) {
|
||||
var isLight = next === "light";
|
||||
btn.textContent = isLight ? "\u2600" : "\u263E";
|
||||
btn.title = isLight ? "Switch to dark theme" : "Switch to light theme";
|
||||
btn.setAttribute(
|
||||
"aria-label",
|
||||
isLight
|
||||
? "Switch to dark mode (currently light)"
|
||||
: "Switch to light mode (currently dark)",
|
||||
isLight ? "Switch to dark theme" : "Switch to light theme",
|
||||
);
|
||||
}
|
||||
window.onThemeChange = function () {
|
||||
updateThemeMenuItem();
|
||||
}
|
||||
reRenderAllMermaid();
|
||||
};
|
||||
updateThemeMenuItem();
|
||||
|
||||
function toggleHamburger() {
|
||||
var menu = document.getElementById("hamburger-menu");
|
||||
var btn = document.getElementById("hamburger-btn");
|
||||
var open = menu.classList.toggle("open");
|
||||
btn.setAttribute("aria-expanded", open ? "true" : "false");
|
||||
if (open) {
|
||||
updateThemeMenuItem();
|
||||
var first = menu.querySelector(".hmenu-item");
|
||||
if (first) first.focus();
|
||||
(function () {
|
||||
var btn = document.getElementById("theme-toggle");
|
||||
if (btn) {
|
||||
var isLight = document.documentElement.dataset.theme === "light";
|
||||
btn.textContent = isLight ? "\u2600" : "\u263E";
|
||||
btn.title = isLight ? "Switch to dark theme" : "Switch to light theme";
|
||||
btn.setAttribute(
|
||||
"aria-label",
|
||||
isLight ? "Switch to dark theme" : "Switch to light theme",
|
||||
);
|
||||
}
|
||||
}
|
||||
function closeHamburger() {
|
||||
document.getElementById("hamburger-menu").classList.remove("open");
|
||||
document
|
||||
.getElementById("hamburger-btn")
|
||||
.setAttribute("aria-expanded", "false");
|
||||
}
|
||||
function hamburgerDashboard() {
|
||||
closeHamburger();
|
||||
toggleDashboard();
|
||||
}
|
||||
function hamburgerTheme() {
|
||||
toggleTheme();
|
||||
closeHamburger();
|
||||
}
|
||||
|
||||
// Close on outside click
|
||||
document.addEventListener("click", function (e) {
|
||||
var wrap = document.getElementById("hamburger-wrap");
|
||||
if (wrap && !wrap.contains(e.target)) closeHamburger();
|
||||
});
|
||||
// Keyboard nav within menu
|
||||
document
|
||||
.getElementById("hamburger-menu")
|
||||
.addEventListener("keydown", function (e) {
|
||||
var items = Array.from(this.querySelectorAll(".hmenu-item"));
|
||||
var idx = items.indexOf(document.activeElement);
|
||||
if (e.key === "ArrowDown") {
|
||||
e.preventDefault();
|
||||
items[(idx + 1) % items.length].focus();
|
||||
} else if (e.key === "ArrowUp") {
|
||||
e.preventDefault();
|
||||
items[(idx - 1 + items.length) % items.length].focus();
|
||||
} else if (e.key === "Home") {
|
||||
e.preventDefault();
|
||||
items[0].focus();
|
||||
} else if (e.key === "End") {
|
||||
e.preventDefault();
|
||||
items[items.length - 1].focus();
|
||||
} else if (e.key === "Escape") {
|
||||
e.preventDefault();
|
||||
closeHamburger();
|
||||
document.getElementById("hamburger-btn").focus();
|
||||
} else if (e.key === "Tab") {
|
||||
closeHamburger();
|
||||
}
|
||||
});
|
||||
// Escape when focus is on the button itself
|
||||
document
|
||||
.getElementById("hamburger-btn")
|
||||
.addEventListener("keydown", function (e) {
|
||||
if (
|
||||
e.key === "Escape" &&
|
||||
document.getElementById("hamburger-menu").classList.contains("open")
|
||||
) {
|
||||
e.preventDefault();
|
||||
closeHamburger();
|
||||
}
|
||||
});
|
||||
})();
|
||||
|
||||
// ===========================================================================
|
||||
// 8. Tab bar
|
||||
@@ -2641,7 +2574,6 @@ function closeWorkstream(wsId) {
|
||||
|
||||
function showDashboard() {
|
||||
dashboardVisible = true;
|
||||
closeHamburger();
|
||||
document.getElementById("dashboard").classList.add("active");
|
||||
document.getElementById("header").inert = true;
|
||||
document.getElementById("tab-bar").inert = true;
|
||||
@@ -3350,16 +3282,6 @@ document.addEventListener("keydown", function (e) {
|
||||
var nwsOverlay = document.getElementById("new-ws-overlay");
|
||||
if (nwsOverlay && nwsOverlay.style.display !== "none") return;
|
||||
|
||||
// Escape: close hamburger first, then dashboard
|
||||
if (
|
||||
e.key === "Escape" &&
|
||||
document.getElementById("hamburger-menu").classList.contains("open")
|
||||
) {
|
||||
e.preventDefault();
|
||||
closeHamburger();
|
||||
document.getElementById("hamburger-btn").focus();
|
||||
return;
|
||||
}
|
||||
if (e.key === "Escape" && dashboardVisible) {
|
||||
e.preventDefault();
|
||||
hideDashboard();
|
||||
|
||||
@@ -13,24 +13,10 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="header">
|
||||
<div id="hamburger-wrap">
|
||||
<button id="hamburger-btn" onclick="toggleHamburger()" aria-label="Menu" aria-haspopup="true" aria-expanded="false" aria-controls="hamburger-menu">
|
||||
<span></span><span></span><span></span>
|
||||
</button>
|
||||
<div id="hamburger-menu" role="menu">
|
||||
<button class="hmenu-item" role="menuitem" tabindex="-1" onclick="hamburgerDashboard()">
|
||||
<span class="hmenu-icon">⌂</span> Dashboard
|
||||
</button>
|
||||
<div class="hmenu-sep" role="separator"></div>
|
||||
<button class="hmenu-item" role="menuitem" tabindex="-1" id="theme-menu-item" onclick="hamburgerTheme()">
|
||||
<span class="hmenu-icon" id="theme-menu-icon">☾</span> <span id="theme-menu-label">Light mode</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<h1>turnstone</h1>
|
||||
<span id="mcp-status" role="status" aria-live="polite"></span>
|
||||
<span id="health-indicator" class="health-ok" role="status" aria-live="polite" aria-atomic="true"></span>
|
||||
<button id="logout-btn" class="header-btn" onclick="logout()" style="display:none">logout</button>
|
||||
<button id="theme-toggle" class="header-btn" onclick="toggleTheme()" aria-label="Toggle light/dark theme" title="Switch to light theme">☾</button>
|
||||
</div>
|
||||
|
||||
<div id="tab-bar" role="toolbar" aria-label="Workstreams">
|
||||
@@ -132,7 +118,7 @@ window.TURNSTONE_KB_SHORTCUTS = [
|
||||
]},
|
||||
{ title: "Navigation", keys: [
|
||||
{ desc: "Navigate table rows", badge: '<span class="kb-key">\u2191</span> <span class="kb-key">\u2193</span>' },
|
||||
{ desc: "Close dashboard / menu", badge: '<span class="kb-key">Esc</span>' }
|
||||
{ desc: "Close dashboard", badge: '<span class="kb-key">Esc</span>' }
|
||||
]},
|
||||
{ title: "General", keys: [
|
||||
{ desc: "Show this help", badge: '<span class="kb-key">?</span>' }
|
||||
|
||||
@@ -43,68 +43,14 @@
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Hamburger menu
|
||||
Theme toggle
|
||||
========================================================================== */
|
||||
#theme-toggle { color: var(--fg); margin-left: auto; font-size: 14px; line-height: 1; }
|
||||
|
||||
/* ==========================================================================
|
||||
Mobile overrides
|
||||
========================================================================== */
|
||||
#hamburger-wrap { position: relative; }
|
||||
#hamburger-btn {
|
||||
background: none;
|
||||
border: 1px solid var(--border-strong);
|
||||
color: var(--fg);
|
||||
border-radius: var(--radius-sm);
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
padding: 0;
|
||||
flex-shrink: 0;
|
||||
transition: background 0.15s, border-color 0.15s;
|
||||
}
|
||||
#hamburger-btn:hover { background: var(--bg-highlight); border-color: var(--accent-dim); }
|
||||
#hamburger-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
||||
#hamburger-btn span { display: block; width: 14px; height: 2px; background: var(--fg); border-radius: 1px; }
|
||||
#hamburger-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: calc(100% + 6px);
|
||||
left: 0;
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-strong);
|
||||
border-radius: var(--radius);
|
||||
min-width: 180px;
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
|
||||
z-index: 40;
|
||||
overflow: hidden;
|
||||
}
|
||||
[data-theme="light"] #hamburger-menu { box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); }
|
||||
#hamburger-menu.open { display: block; }
|
||||
.hmenu-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
width: 100%;
|
||||
padding: 10px 14px;
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--fg);
|
||||
font: inherit;
|
||||
font-family: var(--font-display);
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
white-space: nowrap;
|
||||
transition: background 0.1s;
|
||||
}
|
||||
.hmenu-item:hover { background: var(--bg-highlight); }
|
||||
.hmenu-item:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
|
||||
.hmenu-item .hmenu-icon { width: 16px; text-align: center; font-size: 14px; opacity: 0.8; }
|
||||
.hmenu-sep { height: 1px; background: var(--border-strong); margin: 4px 0; }
|
||||
@media (max-width: 600px) {
|
||||
#hamburger-btn { width: 40px; height: 40px; }
|
||||
.hmenu-item { padding: 12px 14px; }
|
||||
.ws-tab .tab-close { opacity: 1; padding: 4px 6px; font-size: 16px; }
|
||||
#split-btn { display: none; }
|
||||
}
|
||||
@@ -1514,11 +1460,11 @@ body { position: static; }
|
||||
.judge-spinner-dot { animation: none; opacity: 1; }
|
||||
.thinking-indicator::after { animation: none; content: '...'; }
|
||||
.ws-tab, .ws-tab .tab-close, #new-tab-btn, #split-btn,
|
||||
.hmenu-item, .dashboard-card,
|
||||
.dashboard-card,
|
||||
.approval-btn, .approval-feedback-input,
|
||||
#plan-buttons button, .pane-input-area button,
|
||||
.dashboard-new-btn, .dashboard-input,
|
||||
#health-indicator, #hamburger-btn,
|
||||
#health-indicator, #theme-toggle,
|
||||
#mcp-status, .msg-assistant tbody tr,
|
||||
.msg-assistant .img-placeholder,
|
||||
#new-ws-cancel, #new-ws-submit,
|
||||
|
||||
Reference in New Issue
Block a user