CoolFace
Apppublic

camelDeep/codecraft-junior-adventure

sourceHugging Faceupdated 11mo agoView on Hugging Face
0likes
navbar.js188 linesDownload Raw Back to components
1class CustomNavbar extends HTMLElement {2  connectedCallback() {3    this.attachShadow({ mode: 'open' });4    this.shadowRoot.innerHTML = `5      <style>6        nav {7          background: rgba(255, 255, 255, 0.95);8          backdrop-filter: blur(10px);9          padding: 1rem 2rem;10          display: flex;11          justify-content: space-between;12          align-items: center;13          position: fixed;14          width: 100%;15          top: 0;16          left: 0;17          z-index: 1000;18          box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);19          transition: all 0.3s ease;20        }21        22        nav.scrolled {23          background: rgba(255, 255, 255, 0.98);24          box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);25        }26        27        .logo {28          color: #6366F1;29          font-weight: bold;30          font-size: 1.5rem;31          display: flex;32          align-items: center;33          gap: 0.5rem;34        }35        36        .logo-icon {37          color: #8B5CF6;38        }39        40        ul {41          display: flex;42          gap: 2rem;43          list-style: none;44          margin: 0;45          padding: 0;46        }47        48        a {49          color: #4B5563;50          text-decoration: none;51          font-weight: 500;52          transition: all 0.2s ease;53          position: relative;54          padding: 0.5rem 0;55        }56        57        a:hover {58          color: #6366F1;59        }60        61        a.active {62          color: #6366F1;63        }64        65        a::after {66          content: '';67          position: absolute;68          bottom: 0;69          left: 0;70          width: 0;71          height: 2px;72          background-color: #6366F1;73          transition: width 0.3s ease;74        }75        76        a:hover::after,77        a.active::after {78          width: 100%;79        }80        81        .mobile-menu-btn {82          display: none;83          background: none;84          border: none;85          cursor: pointer;86          color: #4B5563;87        }88        89        @media (max-width: 768px) {90          ul {91            position: fixed;92            top: 70px;93            left: 0;94            width: 100%;95            background: white;96            flex-direction: column;97            align-items: center;98            padding: 2rem 0;99            gap: 1.5rem;100            box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);101            transform: translateY(-150%);102            transition: transform 0.3s ease;103            z-index: 999;104          }105          106          ul.open {107            transform: translateY(0);108          }109          110          .mobile-menu-btn {111            display: block;112          }113        }114      </style>115      <nav>116        <a href="/" class="logo">117          <i data-feather="code" class="logo-icon"></i>118          CodeCrafteur119        </a>120        121        <button class="mobile-menu-btn">122          <i data-feather="menu"></i>123        </button>124        125        <ul>126          <li><a href="#services" class="nav-link">Services</a></li>127          <li><a href="#portfolio" class="nav-link">Portfolio</a></li>128          <li><a href="#about" class="nav-link">À propos</a></li>129          <li><a href="#contact" class="nav-link">Contact</a></li>130        </ul>131      </nav>132    `;133    134    // Mobile menu toggle135    const menuBtn = this.shadowRoot.querySelector('.mobile-menu-btn');136    const menu = this.shadowRoot.querySelector('ul');137    138    if (menuBtn && menu) {139      menuBtn.addEventListener('click', () => {140        menu.classList.toggle('open');141        const icon = menuBtn.querySelector('i');142        if (menu.classList.contains('open')) {143          icon.setAttribute('data-feather', 'x');144        } else {145          icon.setAttribute('data-feather', 'menu');146        }147        feather.replace();148      });149    }150    151    // Navbar scroll effect152    const nav = this.shadowRoot.querySelector('nav');153    window.addEventListener('scroll', () => {154      if (window.scrollY > 50) {155        nav.classList.add('scrolled');156      } else {157        nav.classList.remove('scrolled');158      }159    });160    161    // Active link highlighting162    const navLinks = this.shadowRoot.querySelectorAll('.nav-link');163    window.addEventListener('scroll', () => {164      let current = '';165      166      sections.forEach(section => {167        const sectionTop = section.offsetTop;168        const sectionHeight = section.clientHeight;169        170        if (pageYOffset >= (sectionTop - 100)) {171          current = section.getAttribute('id');172        }173      });174      175      navLinks.forEach(link => {176        link.classList.remove('active');177        if (link.getAttribute('href') === `#${current}`) {178          link.classList.add('active');179        }180      });181    });182  }183}184 185customElements.define('custom-navbar', CustomNavbar);186 187// Sections for active link highlighting188const sections = document.querySelectorAll('section');