Add collapsible sidebar menu functionality
Features: - Sidebar can now be collapsed to save screen space (260px → 60px) - Collapse button integrated directly into sidebar header - Smooth animations for expand/collapse transitions - State persistence using localStorage (remembers user preference) - Responsive design - collapse feature disabled on mobile devices - Visual feedback with hover effects and rotation animation - Icons remain visible when collapsed for easy navigation - Seamless integration with existing mobile sidebar toggle User Experience: - Click the "‹" button in sidebar to collapse - Click "›" button to expand back to full width - User preference is saved and restored on page reload - Main content area automatically adjusts width - Smooth 0.3s transition animations for professional feel - Tooltips show current state (Collapse/Expand sidebar) Technical Implementation: - CSS transitions for smooth animations - JavaScript event handling with localStorage persistence - Responsive CSS media queries for mobile compatibility - Graceful degradation on smaller screens - Clean separation of desktop vs mobile behavior 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
31a02a69ac
commit
8f141beef5
@ -9,6 +9,7 @@
|
||||
<body>
|
||||
<div class="app-container">
|
||||
<nav class="sidebar">
|
||||
<button class="sidebar-collapse-btn" id="sidebar-collapse-btn" title="Collapse sidebar">‹</button>
|
||||
<div class="sidebar-header">
|
||||
<h2>ETF Tracker</h2>
|
||||
</div>
|
||||
|
||||
44
script.js
44
script.js
@ -12,6 +12,7 @@ class ETFTradeTracker {
|
||||
this.bindEvents();
|
||||
this.bindNavigation();
|
||||
this.bindAuthEvents();
|
||||
this.bindSidebarToggle();
|
||||
this.setDefaultDateTime();
|
||||
|
||||
// Check if user is logged in
|
||||
@ -73,6 +74,49 @@ class ETFTradeTracker {
|
||||
});
|
||||
}
|
||||
|
||||
bindSidebarToggle() {
|
||||
const sidebarCollapseBtn = document.getElementById('sidebar-collapse-btn');
|
||||
const sidebar = document.querySelector('.sidebar');
|
||||
const mainContent = document.querySelector('.main-content');
|
||||
|
||||
// Load saved sidebar state from localStorage
|
||||
const savedState = localStorage.getItem('sidebarCollapsed');
|
||||
if (savedState === 'true') {
|
||||
sidebar.classList.add('collapsed');
|
||||
mainContent.classList.add('sidebar-collapsed');
|
||||
sidebarCollapseBtn.setAttribute('title', 'Expand sidebar');
|
||||
sidebarCollapseBtn.innerHTML = '›';
|
||||
}
|
||||
|
||||
sidebarCollapseBtn.addEventListener('click', () => {
|
||||
const isCollapsed = sidebar.classList.contains('collapsed');
|
||||
|
||||
if (isCollapsed) {
|
||||
// Expand sidebar
|
||||
sidebar.classList.remove('collapsed');
|
||||
mainContent.classList.remove('sidebar-collapsed');
|
||||
sidebarCollapseBtn.setAttribute('title', 'Collapse sidebar');
|
||||
sidebarCollapseBtn.innerHTML = '‹';
|
||||
localStorage.setItem('sidebarCollapsed', 'false');
|
||||
} else {
|
||||
// Collapse sidebar
|
||||
sidebar.classList.add('collapsed');
|
||||
mainContent.classList.add('sidebar-collapsed');
|
||||
sidebarCollapseBtn.setAttribute('title', 'Expand sidebar');
|
||||
sidebarCollapseBtn.innerHTML = '›';
|
||||
localStorage.setItem('sidebarCollapsed', 'true');
|
||||
}
|
||||
});
|
||||
|
||||
// Handle mobile sidebar toggle (existing functionality)
|
||||
const sidebarToggle = document.querySelector('.sidebar-toggle');
|
||||
if (sidebarToggle) {
|
||||
sidebarToggle.addEventListener('click', () => {
|
||||
sidebar.classList.toggle('open');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
showPage(pageId) {
|
||||
const pages = document.querySelectorAll('.page');
|
||||
const pageTitle = document.getElementById('page-title');
|
||||
|
||||
96
styles.css
96
styles.css
@ -28,10 +28,50 @@ body {
|
||||
position: fixed;
|
||||
height: 100vh;
|
||||
overflow-y: auto;
|
||||
transition: transform 0.3s ease;
|
||||
transition: all 0.3s ease;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.sidebar.collapsed {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.sidebar.collapsed .menu-text,
|
||||
.sidebar.collapsed .sidebar-header h2,
|
||||
.sidebar.collapsed .user-info span,
|
||||
.sidebar.collapsed .logout-btn {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.2s ease, visibility 0.2s ease;
|
||||
}
|
||||
|
||||
.menu-text,
|
||||
.sidebar-header h2,
|
||||
.user-info span,
|
||||
.logout-btn {
|
||||
transition: opacity 0.2s ease, visibility 0.2s ease;
|
||||
}
|
||||
|
||||
.sidebar.collapsed .menu-icon {
|
||||
margin-right: 0;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.sidebar.collapsed .menu-item {
|
||||
justify-content: center;
|
||||
padding: 15px 0;
|
||||
}
|
||||
|
||||
.sidebar.collapsed .sidebar-header {
|
||||
padding: 20px 10px;
|
||||
}
|
||||
|
||||
.sidebar.collapsed .user-info {
|
||||
padding: 15px 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
padding: 30px 20px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
@ -125,6 +165,11 @@ body {
|
||||
margin-left: 260px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transition: margin-left 0.3s ease;
|
||||
}
|
||||
|
||||
.main-content.sidebar-collapsed {
|
||||
margin-left: 60px;
|
||||
}
|
||||
|
||||
.top-header {
|
||||
@ -140,18 +185,45 @@ body {
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
display: none;
|
||||
display: block;
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 1.5rem;
|
||||
cursor: pointer;
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.2s ease;
|
||||
padding: 8px;
|
||||
border-radius: 6px;
|
||||
transition: all 0.2s ease;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.sidebar-toggle:hover {
|
||||
background-color: #f0f0f0;
|
||||
background: #f1f3f4;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.sidebar-collapse-btn {
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 10px;
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 1.2rem;
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s ease;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.sidebar-collapse-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.sidebar.collapsed .sidebar-collapse-btn {
|
||||
right: 15px;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
#page-title {
|
||||
@ -187,6 +259,10 @@ body {
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
.sidebar.collapsed {
|
||||
width: 280px; /* Keep full width on mobile when collapsed */
|
||||
}
|
||||
|
||||
.sidebar.open {
|
||||
transform: translateX(0);
|
||||
}
|
||||
@ -195,10 +271,18 @@ body {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.main-content.sidebar-collapsed {
|
||||
margin-left: 0; /* No change on mobile */
|
||||
}
|
||||
|
||||
.sidebar-toggle {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sidebar-collapse-btn {
|
||||
display: none; /* Hide collapse button on mobile */
|
||||
}
|
||||
|
||||
.content-area {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user