Implementar navbar sticky con Bootstrap 5 y animaciones - Issue #7
Implementación completa de navbar sticky con menú hamburguesa responsive según especificaciones del template del cliente: **Archivos Modificados:** - header.php: Reescritura completa con navbar Bootstrap 5, sticky positioning, y responsive hamburger menu - functions.php: Agregado require para nav-walker.php - inc/enqueue-scripts.php: Agregado enqueue de custom-style.css y main.js **Archivos Creados:** - assets/css/custom-style.css: Estilos navbar con animaciones (gradient underline, dropdown slideDown, etc.) - assets/js/main.js: JavaScript para scroll effect, active menu highlight, y mobile auto-close - inc/nav-walker.php: Bootstrap 5 Nav Walker para dropdowns WordPress **Características:** ✅ Navbar sticky con transición de sombra al hacer scroll ✅ Gradient underline animation en hover de nav-links ✅ Dropdown menus con animación slideDown ✅ Menú hamburguesa responsive (< 991px) ✅ Auto-close mobile menu al hacer click en enlaces ✅ Active menu item highlighting ✅ Smooth scroll para anchor links ✅ Skip link para accesibilidad ✅ Compatible con WordPress menu system 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
144
wp-content/themes/apus-theme/assets/js/main.js
Normal file
144
wp-content/themes/apus-theme/assets/js/main.js
Normal file
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Main JavaScript - APUS Theme
|
||||
*
|
||||
* Funcionalidades principales del tema según template del cliente.
|
||||
* Incluye: Navbar sticky scroll effect y animaciones.
|
||||
*
|
||||
* @package Apus_Theme
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Navbar Scroll Effect
|
||||
* Añade clase 'scrolled' al navbar cuando se hace scroll > 50px
|
||||
*/
|
||||
function initNavbarScrollEffect() {
|
||||
const navbar = document.querySelector('.navbar');
|
||||
|
||||
if (!navbar) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Optimización con throttle para mejor performance
|
||||
let ticking = false;
|
||||
|
||||
function updateNavbar() {
|
||||
if (window.scrollY > 50) {
|
||||
navbar.classList.add('scrolled');
|
||||
} else {
|
||||
navbar.classList.remove('scrolled');
|
||||
}
|
||||
ticking = false;
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', function() {
|
||||
if (!ticking) {
|
||||
window.requestAnimationFrame(updateNavbar);
|
||||
ticking = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Ejecutar una vez al cargar por si la página ya tiene scroll
|
||||
updateNavbar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Highlight Active Menu Item
|
||||
* Marca el item del menú correspondiente a la página actual
|
||||
*/
|
||||
function highlightActiveMenuItem() {
|
||||
const currentUrl = window.location.href;
|
||||
const navLinks = document.querySelectorAll('.navbar-nav .nav-link');
|
||||
|
||||
navLinks.forEach(function(link) {
|
||||
// Remover active de todos
|
||||
link.classList.remove('active');
|
||||
|
||||
// Agregar active si coincide URL
|
||||
if (link.href === currentUrl) {
|
||||
link.classList.add('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Mobile Menu Close on Link Click
|
||||
* Cierra el menú móvil automáticamente al hacer click en un enlace
|
||||
*/
|
||||
function initMobileMenuAutoClose() {
|
||||
const navbarToggler = document.querySelector('.navbar-toggler');
|
||||
const navbarCollapse = document.querySelector('.navbar-collapse');
|
||||
const navLinks = document.querySelectorAll('.navbar-nav .nav-link');
|
||||
|
||||
if (!navbarToggler || !navbarCollapse) {
|
||||
return;
|
||||
}
|
||||
|
||||
navLinks.forEach(function(link) {
|
||||
link.addEventListener('click', function() {
|
||||
// Solo en móvil (cuando el toggler es visible)
|
||||
if (window.getComputedStyle(navbarToggler).display !== 'none') {
|
||||
const bsCollapse = bootstrap.Collapse.getInstance(navbarCollapse);
|
||||
if (bsCollapse) {
|
||||
bsCollapse.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Smooth Scroll for Anchor Links
|
||||
* Scroll suave para enlaces ancla (#)
|
||||
*/
|
||||
function initSmoothScroll() {
|
||||
const anchorLinks = document.querySelectorAll('a[href^="#"]');
|
||||
|
||||
anchorLinks.forEach(function(link) {
|
||||
link.addEventListener('click', function(e) {
|
||||
const targetId = this.getAttribute('href');
|
||||
|
||||
// Ignorar enlaces # vacíos o solo #
|
||||
if (targetId === '#' || targetId === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetElement = document.querySelector(targetId);
|
||||
|
||||
if (targetElement) {
|
||||
e.preventDefault();
|
||||
|
||||
// Offset por el navbar sticky
|
||||
const navbarHeight = document.querySelector('.navbar').offsetHeight;
|
||||
const targetPosition = targetElement.getBoundingClientRect().top + window.pageYOffset - navbarHeight - 20;
|
||||
|
||||
window.scrollTo({
|
||||
top: targetPosition,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize all functions when DOM is ready
|
||||
*/
|
||||
function init() {
|
||||
initNavbarScrollEffect();
|
||||
highlightActiveMenuItem();
|
||||
initMobileMenuAutoClose();
|
||||
initSmoothScroll();
|
||||
}
|
||||
|
||||
// DOM Ready
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user