/** * Tractatus Framework - Responsive Navbar Component * Consistent, mobile-friendly navigation across all pages */ class TractatusNavbar { constructor() { this.mobileMenuOpen = false; this.init(); } init() { this.render(); this.attachEventListeners(); } render() { const navHTML = ` `; // Always insert navbar at the very beginning of body // Check if there's already a tractatus navbar (to avoid duplicates) const existingNavbar = document.querySelector('nav.bg-white.border-b.border-gray-200.sticky'); if (existingNavbar) { existingNavbar.outerHTML = navHTML; } else { document.body.insertAdjacentHTML('afterbegin', navHTML); } } attachEventListeners() { // 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(); }