Merge pull request #146 from gbw/feature/collapsible-mobile-sidebar
feat(ui): add collapsible sidebar for mobile devices
This commit is contained in:
@@ -8,6 +8,51 @@
|
||||
height: 100%;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 2px 0 12px rgba(0,0,0,0.15);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
/* Sidebar overlay for mobile */
|
||||
.sidebar-overlay {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 998;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.sidebar-overlay.active {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Mobile responsive styles */
|
||||
@media (max-width: 768px) {
|
||||
.sidebar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 999;
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
.sidebar.open {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
[dir='rtl'] .sidebar {
|
||||
left: auto;
|
||||
right: 0;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
[dir='rtl'] .sidebar.open {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.logo-container {
|
||||
|
||||
@@ -20,6 +20,42 @@
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Sidebar toggle button (hidden on desktop) */
|
||||
.sidebar-toggle {
|
||||
display: none;
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
color: #4a5568;
|
||||
border-radius: 8px;
|
||||
transition: background-color 0.2s, color 0.2s;
|
||||
margin-right: 12px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sidebar-toggle:hover {
|
||||
background-color: #f7fafc;
|
||||
color: #ff5e3a;
|
||||
}
|
||||
|
||||
.sidebar-toggle i {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
/* Mobile responsive styles for top bar */
|
||||
@media (max-width: 768px) {
|
||||
.top-bar {
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
.search-container {
|
||||
flex-grow: 1;
|
||||
max-width: 600px;
|
||||
|
||||
@@ -201,3 +201,13 @@
|
||||
[data-theme="dark"] .search-sort-select:focus {
|
||||
border-color: #ff5e3a;
|
||||
}
|
||||
|
||||
/* Dark theme for mobile sidebar toggle */
|
||||
[data-theme="dark"] .sidebar-toggle {
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .sidebar-toggle:hover {
|
||||
background-color: #334155;
|
||||
color: #ff5e3a;
|
||||
}
|
||||
|
||||
+7
-1
@@ -57,8 +57,10 @@
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Mobile sidebar overlay -->
|
||||
<div class="sidebar-overlay" id="sidebar-overlay"></div>
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
<div class="sidebar" id="sidebar">
|
||||
<a href="/" class="logo-container" style="text-decoration:none;color:inherit;">
|
||||
|
||||
<div class="logo">
|
||||
@@ -105,6 +107,10 @@
|
||||
<div class="main-content">
|
||||
<!-- Top Bar -->
|
||||
<div class="top-bar">
|
||||
<!-- Mobile menu toggle -->
|
||||
<button class="sidebar-toggle" id="sidebar-toggle" aria-label="Toggle navigation menu">
|
||||
<i class="fas fa-bars"></i>
|
||||
</button>
|
||||
<div class="search-container">
|
||||
<i class="fas fa-search search-icon"></i>
|
||||
<input type="text" id="search-input" data-i18n-placeholder="actions.search" placeholder="Search files, folders...">
|
||||
|
||||
@@ -3,6 +3,70 @@
|
||||
* Extracted from main.js to keep navigation concerns isolated.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Mobile sidebar toggle functionality
|
||||
*/
|
||||
function initSidebarToggle() {
|
||||
const sidebarToggle = document.getElementById('sidebar-toggle');
|
||||
const sidebar = document.getElementById('sidebar');
|
||||
const sidebarOverlay = document.getElementById('sidebar-overlay');
|
||||
|
||||
if (!sidebarToggle || !sidebar || !sidebarOverlay) return;
|
||||
|
||||
function openSidebar() {
|
||||
sidebar.classList.add('open');
|
||||
sidebarOverlay.classList.add('active');
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
function closeSidebar() {
|
||||
sidebar.classList.remove('open');
|
||||
sidebarOverlay.classList.remove('active');
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
|
||||
function toggleSidebar() {
|
||||
if (sidebar.classList.contains('open')) {
|
||||
closeSidebar();
|
||||
} else {
|
||||
openSidebar();
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle button click
|
||||
sidebarToggle.addEventListener('click', toggleSidebar);
|
||||
|
||||
// Close sidebar when clicking overlay
|
||||
sidebarOverlay.addEventListener('click', closeSidebar);
|
||||
|
||||
// Close sidebar on escape key
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && sidebar.classList.contains('open')) {
|
||||
closeSidebar();
|
||||
}
|
||||
});
|
||||
|
||||
// Close sidebar when navigating (nav item click on mobile)
|
||||
const navItems = sidebar.querySelectorAll('.nav-item');
|
||||
navItems.forEach(item => {
|
||||
item.addEventListener('click', () => {
|
||||
if (window.innerWidth <= 768) {
|
||||
closeSidebar();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Expose functions globally
|
||||
window.sidebarToggle = {
|
||||
open: openSidebar,
|
||||
close: closeSidebar,
|
||||
toggle: toggleSidebar
|
||||
};
|
||||
}
|
||||
|
||||
// Initialize sidebar toggle when DOM is ready
|
||||
document.addEventListener('DOMContentLoaded', initSidebarToggle);
|
||||
|
||||
// Mapping of section names to their corresponding view flags
|
||||
const VIEW_FLAGS = {
|
||||
'files': 'isFilesView',
|
||||
|
||||
Reference in New Issue
Block a user