/** * Arod Menu Bar Component * A responsive navigation menu with search and theme toggle * * Usage: * * Papers * Notes * About * */ // ============================================ // AROD-MENU - Main Menu Bar Component // ============================================ class ArodMenu extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); } connectedCallback() { this.render(); this.setupMobileToggle(); } render() { this.shadowRoot.innerHTML = ` `; } setupMobileToggle() { const toggle = this.shadowRoot.querySelector('.mobile-toggle'); const items = this.shadowRoot.querySelector('.menu-items'); toggle?.addEventListener('click', () => { items?.classList.toggle('mobile-open'); }); // Close menu when clicking outside document.addEventListener('click', (e) => { if (!this.contains(e.target)) { items?.classList.remove('mobile-open'); } }); } } // ============================================ // MENU-ITEM - Individual Menu Item Component // ============================================ class MenuItem extends HTMLElement { constructor() { super(); // Store the original text content this._label = ''; } connectedCallback() { // Capture the text content before any rendering this._label = this.textContent.trim(); this.render(); this.setupNavigation(); } render() { const href = this.getAttribute('href') || '#'; // Style the menu-item element itself this.style.cssText = ` display: inline-flex; align-items: center; height: 100%; `; // Create link element const link = document.createElement('a'); link.href = href; link.textContent = this._label; link.style.cssText = ` color: var(--menu-text, #222); text-decoration: none; padding: 0.5rem 0.75rem; border-radius: 4px; transition: all 0.2s ease; display: inline-block; white-space: nowrap; `; // Clear and add link this.innerHTML = ''; this.appendChild(link); // Add hover effects directly to the link link.addEventListener('mouseenter', () => { link.style.color = 'var(--menu-hover, #0066cc)'; link.style.background = 'rgba(0, 102, 204, 0.1)'; }); link.addEventListener('mouseleave', () => { if (!this.hasAttribute('active')) { link.style.color = 'var(--menu-text, #222)'; link.style.background = 'transparent'; } }); } setupNavigation() { // Mark active based on current path const href = this.getAttribute('href'); const link = this.querySelector('a'); if (href && window.location.pathname === href) { this.setAttribute('active', ''); if (link) { link.style.color = 'var(--menu-hover, #0066cc)'; link.style.fontWeight = '500'; } } } } // Register components customElements.define('arod-menu', ArodMenu); customElements.define('menu-item', MenuItem);