Spaces:
Sleeping
Sleeping
Commit
·
50f2f35
1
Parent(s):
1b86f72
Fix mobile navigation: visible toggle, overlay, and correct sidebar behavior
Browse files- frontend/index.html +2 -0
- frontend/main.js +44 -24
- frontend/style.css +41 -12
frontend/index.html
CHANGED
|
@@ -22,6 +22,8 @@
|
|
| 22 |
</nav>
|
| 23 |
</aside>
|
| 24 |
<main class="main-content">
|
|
|
|
|
|
|
| 25 |
<div class="container">
|
| 26 |
<div id="load-dataset" class="page active">
|
| 27 |
<div class="card">
|
|
|
|
| 22 |
</nav>
|
| 23 |
</aside>
|
| 24 |
<main class="main-content">
|
| 25 |
+
<button id="mobile-sidebar-toggle" class="mobile-toggle"><i class="fas fa-bars"></i></button>
|
| 26 |
+
<div class="overlay"></div>
|
| 27 |
<div class="container">
|
| 28 |
<div id="load-dataset" class="page active">
|
| 29 |
<div class="card">
|
frontend/main.js
CHANGED
|
@@ -3,7 +3,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 3 |
const pages = document.querySelectorAll('.page');
|
| 4 |
const sidebar = document.querySelector('.sidebar');
|
| 5 |
const mainContent = document.querySelector('.main-content');
|
| 6 |
-
const
|
|
|
|
|
|
|
| 7 |
const loader = document.querySelector('.loader');
|
| 8 |
|
| 9 |
function animateNavText() {
|
|
@@ -30,6 +32,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 30 |
|
| 31 |
document.getElementById(pageId).classList.add('active');
|
| 32 |
link.classList.add('active');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
});
|
| 34 |
});
|
| 35 |
|
|
@@ -39,41 +47,53 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
| 39 |
}
|
| 40 |
|
| 41 |
// Initial setup for sidebar based on screen size
|
| 42 |
-
|
| 43 |
-
sidebar.classList.add('collapsed'); // Start collapsed on mobile
|
| 44 |
-
mainContent.classList.remove('collapsed'); // Main content always full width on mobile
|
| 45 |
-
} else {
|
| 46 |
-
// Desktop default state (can be adjusted if you want it collapsed by default)
|
| 47 |
-
sidebar.classList.remove('collapsed');
|
| 48 |
-
mainContent.classList.remove('collapsed');
|
| 49 |
-
}
|
| 50 |
-
|
| 51 |
-
sidebarToggle.addEventListener('click', () => {
|
| 52 |
if (isMobileView()) {
|
| 53 |
-
sidebar.classList.
|
| 54 |
-
//
|
|
|
|
|
|
|
| 55 |
} else {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
sidebar.classList.toggle('collapsed');
|
| 57 |
mainContent.classList.toggle('collapsed');
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
}
|
| 62 |
});
|
| 63 |
|
| 64 |
-
//
|
| 65 |
-
|
| 66 |
if (isMobileView()) {
|
| 67 |
-
sidebar.classList.
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
|
|
|
|
|
|
|
|
|
| 72 |
sidebar.classList.remove('active');
|
| 73 |
-
|
| 74 |
}
|
| 75 |
});
|
| 76 |
|
|
|
|
|
|
|
|
|
|
| 77 |
function formatAIResponse(text) {
|
| 78 |
text = text.replace(/\*\*(.*?)\*\*/g, '<strong>$1<\/strong>');
|
| 79 |
text = text.replace(/^\d+\.\s+(.*)/gm, '<li>$1<\/li>');
|
|
|
|
| 3 |
const pages = document.querySelectorAll('.page');
|
| 4 |
const sidebar = document.querySelector('.sidebar');
|
| 5 |
const mainContent = document.querySelector('.main-content');
|
| 6 |
+
const desktopSidebarToggle = document.getElementById('sidebar-toggle'); // Original desktop toggle
|
| 7 |
+
const mobileSidebarToggle = document.getElementById('mobile-sidebar-toggle'); // New mobile toggle
|
| 8 |
+
const overlay = document.querySelector('.overlay'); // New overlay
|
| 9 |
const loader = document.querySelector('.loader');
|
| 10 |
|
| 11 |
function animateNavText() {
|
|
|
|
| 32 |
|
| 33 |
document.getElementById(pageId).classList.add('active');
|
| 34 |
link.classList.add('active');
|
| 35 |
+
|
| 36 |
+
// Close sidebar on mobile after navigation
|
| 37 |
+
if (isMobileView()) {
|
| 38 |
+
sidebar.classList.remove('active');
|
| 39 |
+
overlay.classList.remove('active');
|
| 40 |
+
}
|
| 41 |
});
|
| 42 |
});
|
| 43 |
|
|
|
|
| 47 |
}
|
| 48 |
|
| 49 |
// Initial setup for sidebar based on screen size
|
| 50 |
+
function setupSidebarState() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
if (isMobileView()) {
|
| 52 |
+
sidebar.classList.remove('collapsed'); // Ensure desktop collapsed state is removed
|
| 53 |
+
sidebar.classList.remove('active'); // Start hidden on mobile
|
| 54 |
+
overlay.classList.remove('active');
|
| 55 |
+
mainContent.classList.remove('collapsed'); // Main content always full width on mobile
|
| 56 |
} else {
|
| 57 |
+
// Desktop default state
|
| 58 |
+
sidebar.classList.remove('collapsed');
|
| 59 |
+
sidebar.classList.remove('active'); // Ensure mobile active state is removed
|
| 60 |
+
overlay.classList.remove('active');
|
| 61 |
+
mainContent.classList.remove('collapsed');
|
| 62 |
+
}
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
setupSidebarState(); // Call on initial load
|
| 66 |
+
|
| 67 |
+
// Event listener for desktop sidebar toggle
|
| 68 |
+
desktopSidebarToggle.addEventListener('click', () => {
|
| 69 |
+
if (!isMobileView()) {
|
| 70 |
sidebar.classList.toggle('collapsed');
|
| 71 |
mainContent.classList.toggle('collapsed');
|
| 72 |
+
if (!sidebar.classList.contains('collapsed')) {
|
| 73 |
+
animateNavText();
|
| 74 |
+
}
|
| 75 |
}
|
| 76 |
});
|
| 77 |
|
| 78 |
+
// Event listener for mobile sidebar toggle
|
| 79 |
+
mobileSidebarToggle.addEventListener('click', () => {
|
| 80 |
if (isMobileView()) {
|
| 81 |
+
sidebar.classList.toggle('active');
|
| 82 |
+
overlay.classList.toggle('active');
|
| 83 |
+
}
|
| 84 |
+
});
|
| 85 |
+
|
| 86 |
+
// Event listener for overlay click (to close sidebar on mobile)
|
| 87 |
+
overlay.addEventListener('click', () => {
|
| 88 |
+
if (isMobileView() && sidebar.classList.contains('active')) {
|
| 89 |
sidebar.classList.remove('active');
|
| 90 |
+
overlay.classList.remove('active');
|
| 91 |
}
|
| 92 |
});
|
| 93 |
|
| 94 |
+
// Adjust sidebar on window resize
|
| 95 |
+
window.addEventListener('resize', setupSidebarState);
|
| 96 |
+
|
| 97 |
function formatAIResponse(text) {
|
| 98 |
text = text.replace(/\*\*(.*?)\*\*/g, '<strong>$1<\/strong>');
|
| 99 |
text = text.replace(/^\d+\.\s+(.*)/gm, '<li>$1<\/li>');
|
frontend/style.css
CHANGED
|
@@ -312,8 +312,46 @@ button:hover {
|
|
| 312 |
animation: none;
|
| 313 |
}
|
| 314 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 315 |
/* Responsive adjustments for smaller screens */
|
| 316 |
@media (max-width: 768px) {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 317 |
.app-layout {
|
| 318 |
flex-direction: column;
|
| 319 |
height: auto; /* Allow content to dictate height */
|
|
@@ -321,7 +359,7 @@ button:hover {
|
|
| 321 |
}
|
| 322 |
|
| 323 |
.sidebar {
|
| 324 |
-
width:
|
| 325 |
height: 100vh; /* Full viewport height */
|
| 326 |
position: fixed; /* Keep it fixed for overlay effect */
|
| 327 |
top: 0;
|
|
@@ -340,7 +378,7 @@ button:hover {
|
|
| 340 |
|
| 341 |
.sidebar.collapsed {
|
| 342 |
/* On mobile, 'collapsed' means hidden, so it's the same as default hidden state */
|
| 343 |
-
width:
|
| 344 |
transform: translateX(-100%);
|
| 345 |
}
|
| 346 |
|
|
@@ -353,16 +391,7 @@ button:hover {
|
|
| 353 |
}
|
| 354 |
|
| 355 |
#sidebar-toggle {
|
| 356 |
-
display:
|
| 357 |
-
position: absolute; /* Position relative to sidebar */
|
| 358 |
-
right: 1rem;
|
| 359 |
-
top: 1rem;
|
| 360 |
-
color: var(--text-color-light);
|
| 361 |
-
z-index: 1001; /* Ensure toggle is clickable */
|
| 362 |
-
}
|
| 363 |
-
|
| 364 |
-
.sidebar.active #sidebar-toggle {
|
| 365 |
-
transform: rotate(180deg); /* Rotate when active */
|
| 366 |
}
|
| 367 |
|
| 368 |
.sidebar-nav .nav-link .nav-text {
|
|
|
|
| 312 |
animation: none;
|
| 313 |
}
|
| 314 |
|
| 315 |
+
/* New styles for mobile toggle button */
|
| 316 |
+
.mobile-toggle {
|
| 317 |
+
display: none; /* Hidden by default on desktop */
|
| 318 |
+
position: fixed;
|
| 319 |
+
top: 1rem;
|
| 320 |
+
left: 1rem;
|
| 321 |
+
z-index: 1001; /* Ensure it's above other content */
|
| 322 |
+
background-color: var(--primary-color);
|
| 323 |
+
color: var(--text-color-light);
|
| 324 |
+
border-radius: 50%;
|
| 325 |
+
width: 40px;
|
| 326 |
+
height: 40px;
|
| 327 |
+
display: flex;
|
| 328 |
+
align-items: center;
|
| 329 |
+
justify-content: center;
|
| 330 |
+
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
|
| 331 |
+
}
|
| 332 |
+
|
| 333 |
+
/* Overlay for when sidebar is active */
|
| 334 |
+
.overlay {
|
| 335 |
+
display: none;
|
| 336 |
+
position: fixed;
|
| 337 |
+
top: 0;
|
| 338 |
+
left: 0;
|
| 339 |
+
width: 100%;
|
| 340 |
+
height: 100%;
|
| 341 |
+
background: rgba(0, 0, 0, 0.5);
|
| 342 |
+
z-index: 999; /* Below sidebar, above content */
|
| 343 |
+
}
|
| 344 |
+
|
| 345 |
+
.overlay.active {
|
| 346 |
+
display: block;
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
/* Responsive adjustments for smaller screens */
|
| 350 |
@media (max-width: 768px) {
|
| 351 |
+
.mobile-toggle {
|
| 352 |
+
display: flex; /* Show on mobile */
|
| 353 |
+
}
|
| 354 |
+
|
| 355 |
.app-layout {
|
| 356 |
flex-direction: column;
|
| 357 |
height: auto; /* Allow content to dictate height */
|
|
|
|
| 359 |
}
|
| 360 |
|
| 361 |
.sidebar {
|
| 362 |
+
width: 250px; /* Slightly narrower sidebar for mobile */
|
| 363 |
height: 100vh; /* Full viewport height */
|
| 364 |
position: fixed; /* Keep it fixed for overlay effect */
|
| 365 |
top: 0;
|
|
|
|
| 378 |
|
| 379 |
.sidebar.collapsed {
|
| 380 |
/* On mobile, 'collapsed' means hidden, so it's the same as default hidden state */
|
| 381 |
+
width: 250px;
|
| 382 |
transform: translateX(-100%);
|
| 383 |
}
|
| 384 |
|
|
|
|
| 391 |
}
|
| 392 |
|
| 393 |
#sidebar-toggle {
|
| 394 |
+
display: none; /* Hide the internal sidebar toggle on mobile */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 395 |
}
|
| 396 |
|
| 397 |
.sidebar-nav .nav-link .nav-text {
|