/** * Tractatus Framework - Responsive Navbar Component * Consistent, mobile-friendly navigation across all pages */ class TractatusNavbar { constructor() { this.mobileMenuOpen = false; this.audiencesDropdownOpen = false; this.init(); } init() { this.render(); this.attachEventListeners(); } render() { const navHTML = ` `; // Insert navbar at the beginning of body (or replace existing nav) const existingNav = document.querySelector('nav'); if (existingNav) { existingNav.outerHTML = navHTML; } else { document.body.insertAdjacentHTML('afterbegin', navHTML); } } attachEventListeners() { // Audiences Dropdown (Desktop) const audiencesBtn = document.getElementById('audiences-dropdown-btn'); const audiencesMenu = document.getElementById('audiences-dropdown-menu'); const audiencesArrow = document.getElementById('audiences-dropdown-arrow'); if (audiencesBtn) { audiencesBtn.addEventListener('click', (e) => { e.stopPropagation(); this.audiencesDropdownOpen = !this.audiencesDropdownOpen; audiencesMenu.classList.toggle('hidden', !this.audiencesDropdownOpen); audiencesArrow.style.transform = this.audiencesDropdownOpen ? 'rotate(180deg)' : 'rotate(0deg)'; }); // Close dropdown when clicking outside document.addEventListener('click', () => { if (this.audiencesDropdownOpen) { this.audiencesDropdownOpen = false; audiencesMenu.classList.add('hidden'); audiencesArrow.style.transform = 'rotate(0deg)'; } }); } // Mobile Menu (Navigation Drawer) const mobileMenuBtn = document.getElementById('mobile-menu-btn'); const mobileMenuCloseBtn = document.getElementById('mobile-menu-close-btn'); const mobileMenu = document.getElementById('mobile-menu'); const mobileMenuPanel = document.getElementById('mobile-menu-panel'); const mobileMenuBackdrop = document.getElementById('mobile-menu-backdrop'); const toggleMobileMenu = () => { this.mobileMenuOpen = !this.mobileMenuOpen; if (this.mobileMenuOpen) { // Open: Show menu and slide panel in from right mobileMenu.classList.remove('hidden'); // Use setTimeout to ensure display change happens before animation setTimeout(() => { mobileMenuPanel.classList.remove('translate-x-full'); mobileMenuPanel.classList.add('translate-x-0'); }, 10); document.body.style.overflow = 'hidden'; // Prevent scrolling when menu is open } else { // Close: Slide panel out to right mobileMenuPanel.classList.remove('translate-x-0'); mobileMenuPanel.classList.add('translate-x-full'); // Hide menu after animation completes (300ms) setTimeout(() => { mobileMenu.classList.add('hidden'); }, 300); document.body.style.overflow = ''; } }; // Initialize panel in hidden state (off-screen to the right) if (mobileMenuPanel) { mobileMenuPanel.classList.add('translate-x-full'); } if (mobileMenuBtn) { mobileMenuBtn.addEventListener('click', toggleMobileMenu); } if (mobileMenuCloseBtn) { mobileMenuCloseBtn.addEventListener('click', toggleMobileMenu); } if (mobileMenuBackdrop) { mobileMenuBackdrop.addEventListener('click', toggleMobileMenu); } // Close mobile menu on navigation const mobileLinks = document.querySelectorAll('#mobile-menu a'); mobileLinks.forEach(link => { link.addEventListener('click', () => { if (this.mobileMenuOpen) { toggleMobileMenu(); } }); }); } } // Auto-initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => new TractatusNavbar()); } else { new TractatusNavbar(); }