diff --git a/client/index.html b/client/index.html index cc2cee3..bbc008c 100644 --- a/client/index.html +++ b/client/index.html @@ -9,6 +9,7 @@ +
@@ -26,6 +27,7 @@
+ Select a profile and start a new chat
diff --git a/client/js/app.js b/client/js/app.js index 3522ee2..64b00dd 100644 --- a/client/js/app.js +++ b/client/js/app.js @@ -15,6 +15,9 @@ const profileSelect = document.getElementById('profile-select'); const btnNew = document.getElementById('btn-new'); +const btnSidebarToggle = document.getElementById('btn-sidebar-toggle'); +const sidebarEl = document.querySelector('.sidebar'); +const sidebarBackdrop = document.getElementById('sidebar-backdrop'); const sessionListEl = document.getElementById('session-list'); const chatHeaderEl = document.getElementById('chat-header'); const tokenCounterEl = document.getElementById('token-counter'); @@ -58,6 +61,8 @@ btnAttach.addEventListener('click', () => fileInput.click()); fileInput.addEventListener('change', onFileChange); profileSelect.addEventListener('change', onProfileChange); + btnSidebarToggle.addEventListener('click', toggleSidebar); + sidebarBackdrop.addEventListener('click', closeSidebar); sessionListEl.innerHTML = ''; @@ -363,6 +368,18 @@ // Don't clear pendingImages/pendingFiles — those belong to the user's draft } +// ── Sidebar (mobile) ────────────────────────────────────────────────────────── + +function toggleSidebar() { + sidebarEl.classList.toggle('open'); + sidebarBackdrop.classList.toggle('visible'); +} + +function closeSidebar() { + sidebarEl.classList.remove('open'); + sidebarBackdrop.classList.remove('visible'); +} + // ── Sending ─────────────────────────────────────────────────────────────────── async function sendMessage() { @@ -419,7 +436,7 @@ ? sessions.filter(s => s.profile_id === profileId) : sessions; renderSessions(sessionListEl, visible, currentId, { - onSelect: (id) => { if (id !== currentId) openSession(id); }, + onSelect: (id) => { if (id !== currentId) openSession(id); closeSidebar(); }, onDelete: deleteSession, onPin: pinSession, }); diff --git a/client/style.css b/client/style.css index 4f1c84d..4070371 100644 --- a/client/style.css +++ b/client/style.css @@ -803,3 +803,76 @@ ::-webkit-scrollbar { width: 5px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: #333; border-radius: 99px; } + +/* ── Sidebar toggle button (hidden on desktop) ───────── */ + +.btn-sidebar-toggle { + display: none; + width: 36px; + height: 36px; + flex-shrink: 0; + background: none; + border: 1px solid var(--border); + border-radius: 8px; + color: var(--text-muted); + font-size: 18px; + cursor: pointer; + align-items: center; + justify-content: center; + transition: background 0.15s, color 0.15s; +} +.btn-sidebar-toggle:hover { background: #222; color: var(--text); } + +/* ── Sidebar backdrop (mobile overlay) ───────────────── */ + +.sidebar-backdrop { + display: none; + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.55); + z-index: 99; + opacity: 0; + transition: opacity 0.25s ease; +} +.sidebar-backdrop.visible { + display: block; + opacity: 1; +} + +/* ── Responsive breakpoint ───────────────────────────── */ + +@media (max-width: 768px) { + /* Sidebar becomes a fixed drawer */ + .sidebar { + position: fixed; + left: 0; + top: 0; + height: 100%; + z-index: 100; + transform: translateX(-100%); + transition: transform 0.25s ease; + box-shadow: 4px 0 24px rgba(0, 0, 0, 0.5); + } + .sidebar.open { transform: translateX(0); } + + /* Hamburger button visible */ + .btn-sidebar-toggle { display: flex; } + + /* Chat fills the full width */ + .chat { width: 100%; } + + /* Wider bubbles on small screens */ + .msg { max-width: 90%; } + .tool-card, + .thinking-card, + .summary-card { max-width: 96%; } + + /* Tighter message padding */ + .messages { padding: 16px 12px; gap: 12px; } + + /* Input bar tighter */ + .input-bar { padding: 10px 12px 12px; } + + /* Chat header smaller */ + .chat-header { padding: 10px 14px; min-height: 44px; } +}