// Sidebar Component export class Sidebar { constructor() { this.sidebar = document.getElementById('sidebar'); this.resizeHandle = document.getElementById('resizeHandle'); this.menuToggle = null; this.isResizing = false; this.startX = 0; this.startWidth = 0; this.init(); } init() { this.createMenuToggle(); this.setupResize(); this.setupMobileBehavior(); } createMenuToggle() { // Create mobile menu toggle button this.menuToggle = document.createElement('button'); this.menuToggle.className = 'mobile-menu-toggle'; this.menuToggle.innerHTML = '☰'; this.menuToggle.setAttribute('aria-label', 'Toggle menu'); this.menuToggle.addEventListener('click', (e) => { e.stopPropagation(); this.toggleMobile(); }); // Create overlay for mobile this.overlay = document.createElement('div'); this.overlay.className = 'sidebar-overlay'; this.overlay.addEventListener('click', () => this.closeMobile()); // Insert at the beginning of body document.body.insertBefore(this.menuToggle, document.body.firstChild); document.body.appendChild(this.overlay); } setupResize() { if (!this.resizeHandle || !this.sidebar) return; this.resizeHandle.addEventListener('mousedown', (e) => { if (window.innerWidth <= 768) return; // Disable resize on mobile this.isResizing = true; this.startX = e.clientX; this.startWidth = parseInt(window.getComputedStyle(this.sidebar).width, 10); document.addEventListener('mousemove', this.handleResize.bind(this)); document.addEventListener('mouseup', this.stopResize.bind(this)); e.preventDefault(); }); } handleResize(e) { if (!this.isResizing) return; const width = this.startWidth + e.clientX - this.startX; const minWidth = 200; const maxWidth = 600; if (width >= minWidth && width <= maxWidth) { this.sidebar.style.width = `${width}px`; document.documentElement.style.setProperty('--sidebar-width', `${width}px`); } } stopResize() { this.isResizing = false; document.removeEventListener('mousemove', this.handleResize); document.removeEventListener('mouseup', this.stopResize); } setupMobileBehavior() { // Close sidebar on window resize if switching to desktop window.addEventListener('resize', () => { if (window.innerWidth > 768) { this.closeMobile(); } }); // Close sidebar when clicking on module items or search button on mobile if (this.sidebar) { this.sidebar.addEventListener('click', (e) => { if (window.innerWidth <= 768) { // Close if clicking on interactive elements (but not the toggle itself) if (e.target.closest('.module-item') || e.target.closest('.search-btn') || e.target.closest('.nav-tab')) { // Small delay to allow the click to register setTimeout(() => this.closeMobile(), 100); } } }); } } toggleMobile() { const isOpen = this.sidebar?.classList.contains('open'); if (isOpen) { this.closeMobile(); } else { this.openMobile(); } } openMobile() { this.sidebar?.classList.add('open'); if (this.overlay) { this.overlay.classList.add('active'); } // Prevent body scroll when sidebar is open document.body.style.overflow = 'hidden'; } closeMobile() { this.sidebar?.classList.remove('open'); if (this.overlay) { this.overlay.classList.remove('active'); } // Restore body scroll document.body.style.overflow = ''; } }