camelDeep/codecraft-junior-adventure
0
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');