feat: add overlay click-away handler for sidebar on narrow screens

This commit is contained in:
Brian Krabach
2026-03-27 17:49:07 -07:00
parent cf6f7daf45
commit b62bd3e361
2 changed files with 48 additions and 0 deletions
+25
View File
@@ -448,6 +448,29 @@ function toggleSidebar() {
} }
} }
/**
* Bind a click-away handler on #terminal-container that collapses the sidebar
* when the user taps outside of it in overlay mode (window.innerWidth < 960).
* Returns early without collapsing if:
* - the screen is wide enough that the sidebar is not in overlay mode (>= 960px)
* - the sidebar element is missing
* - the sidebar is already collapsed
*/
function bindSidebarClickAway() {
const container = $('terminal-container');
if (!container) return;
container.addEventListener('click', () => {
if (window.innerWidth >= SIDEBAR_NARROW_THRESHOLD) return;
const sidebar = $('sidebar');
if (!sidebar) return;
if (sidebar.classList.contains('sidebar--collapsed')) return;
sidebar.classList.add('sidebar--collapsed');
try {
localStorage.setItem(SIDEBAR_KEY, JSON.stringify(false));
} catch (_) { /* blocked — ok */ }
});
}
/** /**
* Render the session grid. Shows empty state when no sessions exist. * Render the session grid. Shows empty state when no sessions exist.
* On mobile, sorts sessions by priority before rendering. * On mobile, sorts sessions by priority before rendering.
@@ -972,6 +995,7 @@ function bindStaticEventListeners() {
on($('back-btn'), 'click', closeSession); on($('back-btn'), 'click', closeSession);
on($('sidebar-toggle-btn'), 'click', toggleSidebar); on($('sidebar-toggle-btn'), 'click', toggleSidebar);
on($('sidebar-collapse-btn'), 'click', toggleSidebar); on($('sidebar-collapse-btn'), 'click', toggleSidebar);
bindSidebarClickAway();
on($('palette-trigger'), 'click', openPalette); on($('palette-trigger'), 'click', openPalette);
on($('palette-backdrop'), 'click', closePalette); on($('palette-backdrop'), 'click', closePalette);
document.addEventListener('keydown', handleGlobalKeydown); document.addEventListener('keydown', handleGlobalKeydown);
@@ -1058,6 +1082,7 @@ if (typeof module !== 'undefined' && module.exports) {
renderSidebar, renderSidebar,
initSidebar, initSidebar,
toggleSidebar, toggleSidebar,
bindSidebarClickAway,
renderGrid, renderGrid,
requestNotificationPermission, requestNotificationPermission,
handleBellTransitions, handleBellTransitions,
+23
View File
@@ -2001,3 +2001,26 @@ test('bindStaticEventListeners binds sidebar-toggle-btn and sidebar-collapse-btn
globalThis.document.getElementById = origGetById; globalThis.document.getElementById = origGetById;
globalThis.document.addEventListener = origDocAddListener; globalThis.document.addEventListener = origDocAddListener;
}); });
// --- bindSidebarClickAway ---
test('bindSidebarClickAway is exported and callable', () => {
assert.strictEqual(typeof app.bindSidebarClickAway, 'function', 'bindSidebarClickAway should be a function');
});
test('bindSidebarClickAway registers click listener on terminal-container', () => {
let addEventListenerCalledWith = null;
const mockTerminalContainer = {
addEventListener: (ev, fn) => { addEventListenerCalledWith = ev; },
};
const origGetById = globalThis.document.getElementById;
globalThis.document.getElementById = (id) => {
if (id === 'terminal-container') return mockTerminalContainer;
return null;
};
app.bindSidebarClickAway();
assert.strictEqual(addEventListenerCalledWith, 'click', 'bindSidebarClickAway should register a click listener on terminal-container');
globalThis.document.getElementById = origGetById;
});