|
89 | 89 | position: relative; |
90 | 90 | } |
91 | 91 |
|
92 | | - .nav-center .nav-link { |
| 92 | + .nav-center .nav-link-item { |
93 | 93 | text-decoration: none; |
94 | 94 | color: var(--text-muted); |
95 | 95 | font-weight: 600; |
|
105 | 105 | display: inline-flex; |
106 | 106 | align-items: center; |
107 | 107 | gap: 5px; |
| 108 | + position: relative; |
108 | 109 | } |
109 | 110 |
|
110 | | - .nav-center .nav-link:hover, |
111 | | - .nav-center .nav-link.active-page, |
112 | | - .nav-center .dropdown:hover > .nav-link { |
| 111 | + .nav-center .nav-link-item:hover, |
| 112 | + .nav-center .nav-link-item.active-page, |
| 113 | + .nav-center .dropdown:hover > .nav-link-item { |
113 | 114 | color: var(--accent-blue); |
114 | 115 | } |
115 | 116 |
|
|
343 | 344 | </div> |
344 | 345 | <div class="nav-center" id="navCenter"> |
345 | 346 | <div class="nav-indicator" id="navIndicator"></div> |
346 | | - <a href="/" class="nav-link {% if page.url == '/' %}active-page{% endif %}">Hub</a> |
347 | | - <a href="/newsy" class="nav-link {% if page.url contains 'newsy' %}active-page{% endif %}">Newsy</a> |
348 | | - <a href="/blog" class="nav-link {% if page.url contains 'blog' %}active-page{% endif %}">Blog</a> |
349 | | - <a href="/homelab" class="nav-link {% if page.url contains 'homelab' %}active-page{% endif %}">HomeLab</a> |
350 | | - <a href="/sponsors" class="nav-link {% if page.url contains 'sponsors' %}active-page{% endif %}">Sponsors</a> |
| 347 | + <a href="/" class="nav-link-item {% if page.url == '/' %}active-page{% endif %}">Hub</a> |
| 348 | + <a href="/newsy" class="nav-link-item {% if page.url contains 'newsy' %}active-page{% endif %}">Newsy</a> |
| 349 | + <a href="/blog" class="nav-link-item {% if page.url contains 'blog' %}active-page{% endif %}">Blog</a> |
| 350 | + <a href="/homelab" class="nav-link-item {% if page.url contains 'homelab' %}active-page{% endif %}">HomeLab</a> |
| 351 | + <a href="/sponsors" class="nav-link-item {% if page.url contains 'sponsors' %}active-page{% endif %}">Sponsors</a> |
351 | 352 |
|
352 | | - <div class="dropdown nav-link {% if page.url contains 'orbit' or page.url contains 'homelab-cc' or page.url contains 'phone' or page.url contains 'apps' %}active-page{% endif %}" style="padding: 0;"> |
353 | | - <a href="#" class="nav-link dropbtn" onclick="return false;">Apps ▾</a> |
| 353 | + <div class="dropdown"> |
| 354 | + <a href="#" class="nav-link-item dropbtn {% if page.url contains 'orbit' or page.url contains 'homelab-cc' or page.url contains 'phone' or page.url contains 'apps' %}active-page{% endif %}" onclick="return false;">Apps ▾</a> |
354 | 355 | <div class="dropdown-content"> |
355 | 356 | <div class="dropdown-links-wrapper"> |
356 | 357 | <a href="/orbit">Orbit <span>↗</span></a> |
|
365 | 366 | </div> |
366 | 367 | </div> |
367 | 368 |
|
368 | | - <a href="/benchmarks" class="nav-link {% if page.url contains 'benchmarks' %}active-page{% endif %}">Benchmarks</a> |
369 | | - <a href="/kontakt" class="nav-link {% if page.url contains 'kontakt' %}active-page{% endif %}">Kontakt</a> |
| 369 | + <a href="/benchmarks" class="nav-link-item {% if page.url contains 'benchmarks' %}active-page{% endif %}">Benchmarks</a> |
| 370 | + <a href="/kontakt" class="nav-link-item {% if page.url contains 'kontakt' %}active-page{% endif %}">Kontakt</a> |
370 | 371 | </div> |
371 | 372 | </nav> |
372 | 373 |
|
@@ -457,55 +458,59 @@ <h4>Follow DevLabStudy</h4> |
457 | 458 |
|
458 | 459 | <!-- SKRYPT WSKAŹNIKA NAWIGACJI --> |
459 | 460 | <script> |
460 | | - const navCenter = document.getElementById('navCenter'); |
461 | | - const indicator = document.getElementById('navIndicator'); |
462 | | - // Pobieramy wyłącznie bezpośrednie elementy nawigacyjne poziomu pierwszego |
463 | | - const topNavItems = Array.from(navCenter.querySelectorAll(':scope > .nav-link, :scope > .dropdown')); |
464 | | - const activeItem = navCenter.querySelector('.active-page') || topNavItems[0]; |
| 461 | + document.addEventListener('DOMContentLoaded', () => { |
| 462 | + const navCenter = document.getElementById('navCenter'); |
| 463 | + const indicator = document.getElementById('navIndicator'); |
| 464 | + |
| 465 | + // Pobieramy aktywne linki widoczne na pasku |
| 466 | + const activeLink = navCenter.querySelector('.nav-link-item.active-page') || navCenter.querySelector('.nav-link-item'); |
465 | 467 |
|
466 | | - function moveIndicator(el) { |
467 | | - if (!el) return; |
468 | | - // Pobieramy element przycisku wewnątrz .dropdown lub sam el |
469 | | - const targetEl = el.classList.contains('dropdown') ? el.querySelector('.dropbtn') || el : el; |
470 | | - indicator.style.width = targetEl.offsetWidth + 'px'; |
471 | | - indicator.style.left = targetEl.offsetLeft + 'px'; |
472 | | - } |
| 468 | + function moveIndicatorToEl(targetEl) { |
| 469 | + if (!targetEl) return; |
| 470 | + indicator.style.width = targetEl.offsetWidth + 'px'; |
| 471 | + indicator.style.left = targetEl.offsetLeft + 'px'; |
| 472 | + } |
473 | 473 |
|
474 | | - const savedLeft = sessionStorage.getItem('nav_indicator_left'); |
475 | | - const savedWidth = sessionStorage.getItem('nav_indicator_width'); |
| 474 | + // Prawidłowe załadowanie pozycji po wyrenderowaniu strony |
| 475 | + const savedLeft = sessionStorage.getItem('nav_indicator_left'); |
| 476 | + const savedWidth = sessionStorage.getItem('nav_indicator_width'); |
476 | 477 |
|
477 | | - if (savedLeft !== null && savedWidth !== null) { |
478 | | - indicator.style.transition = 'none'; |
479 | | - indicator.style.left = savedLeft; |
480 | | - indicator.style.width = savedWidth; |
481 | | - void indicator.offsetHeight; |
482 | | - indicator.style.transition = ''; |
483 | | - moveIndicator(activeItem); |
484 | | - } else { |
485 | | - moveIndicator(activeItem); |
486 | | - } |
| 478 | + if (savedLeft !== null && savedWidth !== null) { |
| 479 | + indicator.style.transition = 'none'; |
| 480 | + indicator.style.left = savedLeft + 'px'; |
| 481 | + indicator.style.width = savedWidth + 'px'; |
| 482 | + |
| 483 | + // Wymuszenie przeliczenia przez przeglądarkę |
| 484 | + void indicator.offsetHeight; |
| 485 | + indicator.style.transition = 'width 0.3s cubic-bezier(0.4, 0, 0.2, 1), left 0.3s cubic-bezier(0.4, 0, 0.2, 1)'; |
| 486 | + } else { |
| 487 | + moveIndicatorToEl(activeLink); |
| 488 | + } |
487 | 489 |
|
488 | | - topNavItems.forEach(item => { |
489 | | - // Reagujemy na najechanie na element górnego menu (w tym całe rozwijane menu .dropdown) |
490 | | - item.addEventListener('mouseenter', () => { |
491 | | - moveIndicator(item); |
492 | | - }); |
| 490 | + // Każdy widoczny element w pasku głównym |
| 491 | + const navItems = navCenter.querySelectorAll('.nav-link-item, .dropdown'); |
| 492 | + navItems.forEach(item => { |
| 493 | + const targetHeaderEl = item.classList.contains('dropdown') ? item.querySelector('.dropbtn') : item; |
493 | 494 |
|
494 | | - // Rejestrujemy kliknięcie na wszystkie linki (zarówno z głównego paska jak i rozwijanego menu) |
495 | | - const linksInItem = item.querySelectorAll('a'); |
496 | | - linksInItem.forEach(link => { |
497 | | - link.addEventListener('click', (e) => { |
498 | | - if (link.getAttribute('href') === '#') return; |
499 | | - const targetToSave = item.classList.contains('dropdown') ? (item.querySelector('.dropbtn') || item) : item; |
500 | | - sessionStorage.setItem('nav_indicator_left', targetToSave.offsetLeft + 'px'); |
501 | | - sessionStorage.setItem('nav_indicator_width', targetToSave.offsetWidth + 'px'); |
| 495 | + item.addEventListener('mouseenter', () => { |
| 496 | + moveIndicatorToEl(targetHeaderEl); |
| 497 | + }); |
| 498 | + |
| 499 | + // Rejestrujemy kliknięcie w link i zapisujemy pozycję docelową |
| 500 | + const allAnchors = item.querySelectorAll('a'); |
| 501 | + allAnchors.forEach(anchor => { |
| 502 | + anchor.addEventListener('click', () => { |
| 503 | + if (anchor.getAttribute('href') === '#') return; |
| 504 | + sessionStorage.setItem('nav_indicator_left', targetHeaderEl.offsetLeft); |
| 505 | + sessionStorage.setItem('nav_indicator_width', targetHeaderEl.offsetWidth); |
| 506 | + }); |
502 | 507 | }); |
503 | 508 | }); |
504 | | - }); |
505 | 509 |
|
506 | | - // Wskaźnik wraca do aktywnej zakładki dopiero gdy kursor opuści cały navCenter |
507 | | - navCenter.addEventListener('mouseleave', () => { |
508 | | - moveIndicator(activeItem); |
| 510 | + // Po opuszczeniu paska nawigacji powróć do aktywnej strony |
| 511 | + navCenter.addEventListener('mouseleave', () => { |
| 512 | + moveIndicatorToEl(activeLink); |
| 513 | + }); |
509 | 514 | }); |
510 | 515 | </script> |
511 | 516 | </body> |
|
0 commit comments