From 89a79738c45f2ea2e6dd81f6f3bc2fae36caaab4 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 9 Sep 2026 19:31:44 +0200 Subject: [PATCH] fix: collapsing the saved-chats rail no longer hands the chat column to the citations panel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit .assistant-layout.history-collapsed set display:none on .assistant-history, which removes it from grid flow. The layout still declared three tracks (0 / minmax(0,1fr) / 330px), so the two remaining items shifted left: .assistant-main took the 0 track and #assistant-sources took the 1fr. Collapsing the sidebar made the chat vanish and rendered the citations in its place. The rail is now a zero-width, visibility:hidden grid item, so the columns stay where they belong. Also: inside the assistant workspace the topbar no longer repeats "AI Clinical Assistant" — the page is the assistant. It stays in the DOM, visually hidden, so screen readers still announce it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01BkfrkQwA4YGrGw9LZSpeAq --- public/css/assistant.css | 8 +++++++- test/assistant-workspace-layout.test.js | 27 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/public/css/assistant.css b/public/css/assistant.css index 62ae3058..79b294b7 100644 --- a/public/css/assistant.css +++ b/public/css/assistant.css @@ -4,6 +4,9 @@ .assistant-topbar { display:flex; align-items:center; gap:12px; padding:6px 12px; border-bottom:1px solid var(--g200); background:var(--g50); position:sticky; top:0; z-index:4; } .assistant-topbar-title { flex:1; min-width:0; } .assistant-topbar-title h2 { font-size:15px; margin:0; color:var(--g800); } +/* Inside the assistant workspace the page IS the assistant; naming it again in + the topbar just costs a row of space. Kept in the DOM for screen readers. */ +body.assistant-workspace .assistant-topbar-title h2 { position:absolute; width:1px; height:1px; margin:-1px; padding:0; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; } .assistant-topbar-title h2 i { margin-right:6px; } .assistant-status { display:flex; align-items:center; gap:6px; font-size:12px; color:var(--g500); background:white; border:1px solid var(--g200); border-radius:999px; padding:5px 10px; box-shadow:var(--shadow); } .assistant-dot { width:8px; height:8px; border-radius:50%; background:var(--green); display:inline-block; } @@ -282,7 +285,10 @@ body.assistant-workspace .assistant-layout { height: calc(100vh - 64px); min-hei space, animated so the change reads as a fold rather than a jump. */ .assistant-layout { transition:grid-template-columns .18s ease; } .assistant-layout.history-collapsed { grid-template-columns:0 minmax(0,1fr) 330px; } -.assistant-layout.history-collapsed .assistant-history { display:none; } +/* NOT display:none — that removes the rail from grid flow, so the chat inherits + the 0 column and the sources column takes its place. Keep it as a zero-width + grid item so the remaining columns stay where they belong. */ +.assistant-layout.history-collapsed .assistant-history { width:0; min-width:0; overflow:hidden; visibility:hidden; padding:0; border:0; margin:0; pointer-events:none; } @media (prefers-reduced-motion:reduce) { .assistant-layout { transition:none; } } body.assistant-workspace .assistant-layout > * { min-height: 0; } body.assistant-workspace .assistant-main, diff --git a/test/assistant-workspace-layout.test.js b/test/assistant-workspace-layout.test.js index 5a9ebd39..980dd539 100644 --- a/test/assistant-workspace-layout.test.js +++ b/test/assistant-workspace-layout.test.js @@ -135,3 +135,30 @@ test('the saved-chats rail toggle is visible and states which way it goes', () = assert.match(js, /syncHistoryToggle\(startCollapsed\)/, 'and on restore from localStorage'); assert.match(js, /Show saved chats/, 'the label flips so the collapsed state is escapable'); }); + +test('collapsing the rail does not hand the chat column to the citations panel', () => { + const fs = require('node:fs'); + const path = require('node:path'); + const css = fs.readFileSync(path.join(__dirname, '..', 'public/css/assistant.css'), 'utf8'); + const collapsed = css.split('\n').find(l => l.startsWith('.assistant-layout.history-collapsed .assistant-history')); + assert.ok(collapsed, 'the collapsed rail rule exists'); + // display:none removes the rail from grid flow, so .assistant-main inherits the + // 0 column and #assistant-sources takes the 1fr — the chat vanishes and the + // citations render in its place. + assert.doesNotMatch(collapsed, /display:\s*none/, 'the rail must stay a grid item'); + assert.match(collapsed, /width:0/); + assert.match(collapsed, /visibility:hidden/); + const track = css.split('\n').find(l => l.startsWith('.assistant-layout.history-collapsed {')); + assert.match(track, /grid-template-columns:0 minmax\(0,1fr\) 330px/, 'three tracks for three items'); +}); + +test('the assistant workspace does not repeat its own name in the topbar', () => { + const fs = require('node:fs'); + const path = require('node:path'); + const css = fs.readFileSync(path.join(__dirname, '..', 'public/css/assistant.css'), 'utf8'); + const rule = css.split('\n').find(l => l.startsWith('body.assistant-workspace .assistant-topbar-title h2')); + assert.ok(rule, 'the title is hidden inside the workspace'); + assert.match(rule, /clip:rect\(0 0 0 0\)/, 'visually hidden, still read by screen readers'); + const html = fs.readFileSync(path.join(__dirname, '..', 'public/components/assistant.html'), 'utf8'); + assert.match(html, /AI Clinical Assistant/, 'and still present in the DOM'); +});