diff --git a/assets/css/base.css b/assets/css/base.css index ebf3b03..6e4c566 100644 --- a/assets/css/base.css +++ b/assets/css/base.css @@ -1449,11 +1449,7 @@ select option:checked { border: 1px solid var(--border-color); transition: var(--transition-default); } -.lt-sidebar.collapsed { width: 32px; overflow: hidden; } -.lt-sidebar.collapsed .lt-sidebar-body { display: none; } -.lt-sidebar.collapsed .lt-sidebar-header { justify-content: center; padding: 0.5rem 0; border-bottom: none; } -.lt-sidebar.collapsed .lt-sidebar-header > span:first-child { display: none; } -.lt-sidebar.collapsed .lt-sidebar-toggle { font-size: 0.8rem; padding: 0.4rem; color: var(--accent-cyan); } +.lt-sidebar.collapsed { display: none; } .lt-sidebar-header { display: flex; @@ -5589,6 +5585,33 @@ body.lt-is-offline .lt-main { margin-top: 2rem; transition: margin-top 0.25s eas .lt-footer { flex-direction: column; align-items: flex-start; gap: 0.25rem; } } +.lt-footer-hints { display: flex; align-items: center; flex-wrap: wrap; gap: 0.25rem; } + +.lt-footer-hint { + /* reset button defaults */ + all: unset; + cursor: pointer; + display: inline-flex; + align-items: center; + gap: 0.25rem; + color: var(--text-muted); + font-size: 0.7rem; + font-family: var(--font-mono); + white-space: nowrap; +} +.lt-footer-hint:hover { color: var(--accent-cyan); } +.lt-footer-hint:focus-visible { outline: 1px dashed var(--accent-cyan); outline-offset: 2px; } + +.lt-footer-key { + color: var(--accent-cyan); + opacity: 0.8; +} + +.lt-footer-sep { + color: var(--border-dim); + user-select: none; +} + /* ================================================================ BLINKING CURSOR

SYSTEM STATUS

diff --git a/assets/js/base.js b/assets/js/base.js index 7bdbdf1..91a8b00 100644 --- a/assets/js/base.js +++ b/assets/js/base.js @@ -391,7 +391,10 @@ let combo = ''; if (e.ctrlKey || e.metaKey) combo += 'ctrl+'; if (e.altKey) combo += 'alt+'; - if (e.shiftKey) combo += 'shift+'; + // Only add shift+ for letter keys — for symbol keys (?, !, @, etc.) the shift state + // is already encoded in e.key itself, so adding shift+ would break registrations like '?'. + const isLetter = e.key.length === 1 && /[a-zA-Z]/.test(e.key); + if (e.shiftKey && isLetter) combo += 'shift+'; combo += e.key.toLowerCase(); const alwaysFire = e.key === 'Escape' || e.ctrlKey || e.metaKey; if (inInput && !alwaysFire) return; diff --git a/assets/js/dashboard.js b/assets/js/dashboard.js index e48ddb2..b81fcae 100644 --- a/assets/js/dashboard.js +++ b/assets/js/dashboard.js @@ -3,15 +3,11 @@ */ function toggleSidebar() { const sidebar = document.getElementById('lt-sidebar'); + const btn = document.getElementById('lt-sidebar-toggle-btn'); if (!sidebar) return; - const isCollapsed = sidebar.classList.toggle('collapsed'); - const btn = sidebar.querySelector('.lt-sidebar-toggle'); - if (btn) { - btn.textContent = isCollapsed ? '\u25B6' : '\u25C0'; - btn.setAttribute('aria-label', isCollapsed ? 'Expand filter sidebar' : 'Collapse filter sidebar'); - btn.setAttribute('aria-expanded', isCollapsed ? 'false' : 'true'); - } - localStorage.setItem('sidebarCollapsed', isCollapsed ? 'true' : 'false'); + const isHidden = sidebar.classList.toggle('collapsed'); + localStorage.setItem('sidebarCollapsed', isHidden ? 'true' : 'false'); + if (btn) btn.textContent = isHidden ? '\u22EE\u22EE Show Filters' : '\u22EE\u22EE Filters'; } /** @@ -76,28 +72,20 @@ function initMobileSidebar() { } -// Restore sidebar state and bind toggle button directly (no event delegation) +// Restore sidebar state and bind toggle button document.addEventListener('DOMContentLoaded', function() { const savedState = localStorage.getItem('sidebarCollapsed'); - const sidebar = document.getElementById('lt-sidebar'); + const sidebar = document.getElementById('lt-sidebar'); + const toggleBtn = document.getElementById('lt-sidebar-toggle-btn'); + if (savedState === 'true' && sidebar) { sidebar.classList.add('collapsed'); - const btn = sidebar.querySelector('.lt-sidebar-toggle'); - if (btn) { - btn.textContent = '\u25B6'; - btn.setAttribute('aria-label', 'Expand filter sidebar'); - btn.setAttribute('aria-expanded', 'false'); - } + if (toggleBtn) toggleBtn.textContent = '\u22EE\u22EE Show Filters'; } - // Bind directly — bypass event delegation entirely so it works - // regardless of isDashboard guard or overflow/clipping issues - document.querySelectorAll('.lt-sidebar-toggle').forEach(function(btn) { - btn.addEventListener('click', function(e) { - e.stopPropagation(); - toggleSidebar(); - }); - }); + if (toggleBtn) { + toggleBtn.addEventListener('click', toggleSidebar); + } }); // Main initialization diff --git a/views/DashboardView.php b/views/DashboardView.php index c0a542d..79a3251 100644 --- a/views/DashboardView.php +++ b/views/DashboardView.php @@ -409,12 +409,6 @@ include __DIR__ . '/layout_header.php';