fix: the assistant loads again, the switch fits, and a hidden menu can be brought back
Three faults from moving the switch into the app sidebar: 1. Clicking Assistant did nothing. activateTab() bailed unless a matching .tab-btn existed, and removing the "AI Assistant" nav entry removed exactly that — so every /assistant visit fell through to the fallback tab. A tab reached from the mode switch legitimately has a section without a button, so activateTab now keys off the section and only touches the button if present. 2. The switch overflowed its box. The sidebar is 210px; without min-width:0 the two buttons refused to shrink below their content. They now shrink, with a slightly tighter font and gap so both labels fit. 3. "Hide menu" had no way back. The toggle sits inside the sidebar it collapses, so it disappeared with it. It now leaves the collapsing box and pins itself beside the content, in both the app sidebar and the assistant rail, and the label already flips to "Show menu". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WjVc5oaAaYFNbZGLeJp6TX
This commit is contained in:
parent
6c2bafbe02
commit
b9038eafcc
3 changed files with 27 additions and 11 deletions
|
|
@ -1217,9 +1217,11 @@ button, a, .btn-sm, .btn-generate, .btn-send, .tab-btn, input, textarea, select,
|
|||
/* ── Assistant / Workspace switch ────────────────────────────────────────────
|
||||
Rendered identically in the app sidebar and the assistant rail, so moving
|
||||
between them changes which pill is highlighted and nothing else. */
|
||||
.assistant-mode-switch { display:grid; grid-template-columns:1fr 1fr; gap:4px; margin:8px 12px 10px; padding:4px; background:var(--g100); border:1px solid var(--g200); border-radius:10px; }
|
||||
.assistant-mode-switch button { display:flex; align-items:center; justify-content:center; gap:6px; border:0; border-radius:7px; padding:7px 6px; font-family:inherit; font-size:12px; font-weight:600; color:var(--g600); background:transparent; cursor:pointer; }
|
||||
.assistant-mode-switch button i { font-size:11px; }
|
||||
/* The sidebar is 210px wide. Without min-width:0 the buttons refuse to shrink
|
||||
below their content and the switch overflows its own box. */
|
||||
.assistant-mode-switch { display:grid; grid-template-columns:1fr 1fr; gap:4px; margin:8px 12px 10px; padding:4px; background:var(--g100); border:1px solid var(--g200); border-radius:10px; box-sizing:border-box; max-width:calc(100% - 24px); }
|
||||
.assistant-mode-switch button { display:flex; align-items:center; justify-content:center; gap:5px; min-width:0; border:0; border-radius:7px; padding:7px 4px; font-family:inherit; font-size:11.5px; font-weight:600; color:var(--g600); background:transparent; cursor:pointer; white-space:nowrap; overflow:hidden; }
|
||||
.assistant-mode-switch button i { font-size:11px; flex:0 0 auto; }
|
||||
.assistant-mode-switch button:hover { color:var(--g900); }
|
||||
.assistant-mode-switch button.active { background:white; color:var(--blue); box-shadow:var(--shadow); }
|
||||
/* Inside the assistant rail the gutters already exist, so it only needs the gap. */
|
||||
|
|
@ -1232,11 +1234,17 @@ button, a, .btn-sm, .btn-generate, .btn-send, .tab-btn, input, textarea, select,
|
|||
|
||||
/* Hidden menu: the rail collapses in both places, and the layout takes the
|
||||
space back rather than leaving a gutter. */
|
||||
body.menu-hidden .sidebar { width:0; border:none; overflow:hidden; }
|
||||
/* Collapsing must not take the control away with it, or there is no way back.
|
||||
The toggle leaves the collapsing box and pins itself beside the content. */
|
||||
body.menu-hidden .sidebar { width:0; border:none; overflow:visible; }
|
||||
body.menu-hidden .sidebar > *:not(.sidebar-nav) { display:none; }
|
||||
body.menu-hidden .sidebar-nav > *:not(.assistant-menu-toggle) { display:none; }
|
||||
body.menu-hidden .assistant-menu-toggle,
|
||||
body.assistant-workspace.menu-hidden .assistant-history .assistant-menu-toggle {
|
||||
position:fixed; top:76px; left:10px; z-index:120; margin:0; background:white; box-shadow:var(--shadow); }
|
||||
body.assistant-workspace.menu-hidden .assistant-menu-toggle { top:10px; }
|
||||
body.assistant-workspace.menu-hidden .assistant-layout { grid-template-columns:0 minmax(0,1fr) 330px; }
|
||||
body.assistant-workspace.menu-hidden.assistant-no-citations .assistant-layout { grid-template-columns:0 minmax(0,1fr); }
|
||||
body.assistant-workspace.menu-hidden .assistant-history > *:not(.assistant-menu-toggle) { display:none; }
|
||||
body.assistant-workspace.menu-hidden .assistant-history { width:0; min-width:0; overflow:visible; padding:0; }
|
||||
/* The toggle must survive its own collapse, or there is no way back. */
|
||||
body.assistant-workspace.menu-hidden .assistant-history .assistant-menu-toggle { position:absolute; left:8px; top:8px; z-index:5; }
|
||||
@media (max-width:640px) { .assistant-menu-toggle { display:none; } body.menu-hidden .sidebar { width:auto; } }
|
||||
|
|
|
|||
|
|
@ -100,12 +100,15 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
// --- TAB NAVIGATION ---
|
||||
function activateTab(tabName) {
|
||||
var btn = document.querySelector('.tab-btn[data-tab="' + tabName + '"]');
|
||||
if (!btn || btn.classList.contains('hidden')) return false;
|
||||
var tabEl = document.getElementById(tabName + '-tab');
|
||||
// The assistant is reached from the mode switch, not a sidebar button, so a
|
||||
// tab can legitimately have a section without one. Requiring a button here
|
||||
// silently sent every /assistant visit to the fallback tab instead.
|
||||
if (btn ? btn.classList.contains('hidden') : !tabEl) return false;
|
||||
var activation = ++_tabActivation;
|
||||
document.querySelectorAll('.tab-btn').forEach(function(b) { b.classList.remove('active'); });
|
||||
document.querySelectorAll('.tab-content').forEach(function(c) { c.classList.remove('active'); });
|
||||
btn.classList.add('active');
|
||||
var tabEl = document.getElementById(tabName + '-tab');
|
||||
if (btn) btn.classList.add('active');
|
||||
if (tabEl) {
|
||||
tabEl.classList.add('active');
|
||||
// Lazy-load component HTML, then fire tabChanged after DOM is ready
|
||||
|
|
|
|||
|
|
@ -115,8 +115,13 @@ test('one menu toggle serves both the app sidebar and the assistant rail', () =>
|
|||
// Shared chrome lives in styles.css: the app page never loads assistant.css.
|
||||
const css = read('public/css/styles.css');
|
||||
assert.match(css, /body\.menu-hidden \.sidebar \{ width:0/);
|
||||
assert.match(css, /body\.assistant-workspace\.menu-hidden \.assistant-history \.assistant-menu-toggle \{ position:absolute/,
|
||||
'the toggle survives its own collapse, or there is no way back');
|
||||
// The toggle lives inside the box it collapses, so it must leave that box or
|
||||
// there is no way to bring the menu back.
|
||||
assert.match(css, /body\.menu-hidden \.assistant-menu-toggle,\n[^\n]*assistant-menu-toggle \{\n\s*position:fixed/,
|
||||
'the toggle pins itself outside the collapsed menu');
|
||||
assert.match(css, /body\.menu-hidden \.sidebar-nav > \*:not\(\.assistant-menu-toggle\) \{ display:none; \}/,
|
||||
'everything else in the collapsed sidebar is hidden');
|
||||
assert.match(read('public/js/app.js'), /'Show menu' : 'Hide menu'/, 'and it says how to get back');
|
||||
});
|
||||
|
||||
test('mobile drawer rows carry no chat icons and keep the options menu', () => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue