mobile: off-canvas sidebar, responsive grids/charts/top-bar
- Sidebar becomes slide-in overlay under 768px with backdrop - Hamburger button in top-bar for mobile nav toggle - Grids stack single-column, charts shrink to 280px - Tables scroll horizontally with touch momentum - Status text hidden on mobile (dot stays visible) - Card headers/actions stack vertically - Period selectors scroll horizontally also: image size validation clamp in handleImageGenerations
This commit is contained in:
+57
-5
@@ -60,23 +60,75 @@ class Dashboard {
|
||||
const toggleBtn = document.getElementById('sidebar-toggle');
|
||||
const sidebar = document.querySelector('.sidebar');
|
||||
const logoutBtn = document.getElementById('logout-btn');
|
||||
|
||||
const backdrop = document.getElementById('sidebar-backdrop');
|
||||
const mobileBtn = document.getElementById('mobile-menu-btn');
|
||||
|
||||
const isMobile = () => window.innerWidth < 768;
|
||||
|
||||
const closeMobileNav = () => {
|
||||
if (sidebar) sidebar.classList.remove('mobile-visible');
|
||||
if (backdrop) backdrop.classList.remove('visible');
|
||||
};
|
||||
|
||||
const toggleMobileNav = () => {
|
||||
if (!sidebar || !backdrop) return;
|
||||
const opening = !sidebar.classList.contains('mobile-visible');
|
||||
sidebar.classList.toggle('mobile-visible', opening);
|
||||
backdrop.classList.toggle('visible', opening);
|
||||
document.body.style.overflow = opening && isMobile() ? 'hidden' : '';
|
||||
};
|
||||
|
||||
if (toggleBtn && sidebar) {
|
||||
toggleBtn.onclick = () => {
|
||||
sidebar.classList.toggle('collapsed');
|
||||
localStorage.setItem('sidebar_collapsed', sidebar.classList.contains('collapsed'));
|
||||
if (isMobile()) {
|
||||
toggleMobileNav();
|
||||
} else {
|
||||
sidebar.classList.toggle('collapsed');
|
||||
localStorage.setItem('sidebar_collapsed', sidebar.classList.contains('collapsed'));
|
||||
}
|
||||
};
|
||||
|
||||
if (localStorage.getItem('sidebar_collapsed') === 'true') {
|
||||
|
||||
if (!isMobile() && localStorage.getItem('sidebar_collapsed') === 'true') {
|
||||
sidebar.classList.add('collapsed');
|
||||
}
|
||||
}
|
||||
|
||||
if (mobileBtn) {
|
||||
mobileBtn.onclick = toggleMobileNav;
|
||||
}
|
||||
|
||||
if (backdrop) {
|
||||
backdrop.onclick = closeMobileNav;
|
||||
}
|
||||
|
||||
// Close sidebar on page navigation (mobile)
|
||||
const menuItems = document.querySelectorAll('.menu-item');
|
||||
menuItems.forEach(item => {
|
||||
const origClick = item.onclick;
|
||||
item.onclick = (e) => {
|
||||
if (isMobile()) closeMobileNav();
|
||||
if (origClick) origClick(e);
|
||||
};
|
||||
});
|
||||
|
||||
if (logoutBtn) {
|
||||
logoutBtn.onclick = () => {
|
||||
if (isMobile()) closeMobileNav();
|
||||
window.authManager.logout();
|
||||
};
|
||||
}
|
||||
|
||||
// Handle resize
|
||||
let resizeTimer;
|
||||
window.addEventListener('resize', () => {
|
||||
clearTimeout(resizeTimer);
|
||||
resizeTimer = setTimeout(() => {
|
||||
if (!isMobile()) {
|
||||
closeMobileNav();
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
}, 200);
|
||||
});
|
||||
}
|
||||
|
||||
setupRefresh() {
|
||||
|
||||
Reference in New Issue
Block a user