Initial commit SteelBase - Oficiais e Funcionando
This commit is contained in:
127
js/ui/mobile-menu.js
Normal file
127
js/ui/mobile-menu.js
Normal file
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* Mobile Menu - Hamburger Navigation
|
||||
* Handles mobile sidebar drawer with smooth animations
|
||||
*/
|
||||
|
||||
export function initMobileMenu() {
|
||||
// Only initialize on mobile/tablet
|
||||
if (window.innerWidth >= 1024) return;
|
||||
|
||||
// Create hamburger button
|
||||
const hamburger = createHamburgerButton();
|
||||
|
||||
// Place hamburger inside header/topbar actions
|
||||
const headerActions = document.querySelector('.header-actions');
|
||||
if (headerActions) {
|
||||
headerActions.appendChild(hamburger);
|
||||
} else {
|
||||
// Fallback: add to body if header not found
|
||||
document.body.appendChild(hamburger);
|
||||
}
|
||||
|
||||
// Get sidebar
|
||||
const sidebar = document.querySelector('.sidebar');
|
||||
if (!sidebar) return;
|
||||
// Accessibility roles
|
||||
sidebar.setAttribute('role', 'navigation');
|
||||
sidebar.setAttribute('aria-label', 'Menu principal');
|
||||
|
||||
// Toggle menu function
|
||||
const toggleMenu = () => {
|
||||
const isOpen = hamburger.classList.contains('open');
|
||||
|
||||
hamburger.classList.toggle('open');
|
||||
sidebar.classList.toggle('open');
|
||||
|
||||
// Accessibility
|
||||
hamburger.setAttribute('aria-expanded', String(!isOpen));
|
||||
sidebar.setAttribute('aria-hidden', String(isOpen));
|
||||
};
|
||||
|
||||
// Event listeners
|
||||
hamburger.addEventListener('click', toggleMenu);
|
||||
// Close menu when clicking sidebar item
|
||||
document.querySelectorAll('.sidebar-item').forEach(item => {
|
||||
// Make items focusable for keyboard navigation
|
||||
if (!item.hasAttribute('tabindex')) item.setAttribute('tabindex', '0');
|
||||
item.addEventListener('click', () => {
|
||||
if (window.innerWidth < 1024 && hamburger.classList.contains('open')) {
|
||||
// Slide left then close
|
||||
sidebar.classList.add('closing-left');
|
||||
setTimeout(() => {
|
||||
sidebar.classList.remove('closing-left');
|
||||
toggleMenu();
|
||||
}, 250);
|
||||
}
|
||||
});
|
||||
// Keyboard activation closes menu
|
||||
item.addEventListener('keydown', (e) => {
|
||||
if ((e.key === 'Enter' || e.key === ' ') && window.innerWidth < 1024 && hamburger.classList.contains('open')) {
|
||||
e.preventDefault();
|
||||
sidebar.classList.add('closing-left');
|
||||
setTimeout(() => {
|
||||
sidebar.classList.remove('closing-left');
|
||||
toggleMenu();
|
||||
}, 250);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Handle resize - close menu and cleanup on desktop
|
||||
let resizeTimer;
|
||||
window.addEventListener('resize', () => {
|
||||
clearTimeout(resizeTimer);
|
||||
resizeTimer = setTimeout(() => {
|
||||
if (window.innerWidth >= 1024) {
|
||||
// Desktop - cleanup mobile menu
|
||||
if (hamburger.classList.contains('open')) {
|
||||
toggleMenu();
|
||||
}
|
||||
hamburger.style.display = 'none';
|
||||
} else {
|
||||
// Mobile - show menu button
|
||||
hamburger.style.display = 'flex';
|
||||
}
|
||||
}, 250);
|
||||
});
|
||||
|
||||
// Keyboard navigation and focus management
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && hamburger.classList.contains('open')) {
|
||||
toggleMenu();
|
||||
hamburger.focus();
|
||||
}
|
||||
});
|
||||
|
||||
// Manage focus when opening
|
||||
hamburger.addEventListener('click', () => {
|
||||
if (hamburger.classList.contains('open')) {
|
||||
const firstItem = sidebar.querySelector('.sidebar-item');
|
||||
if (firstItem) firstItem.focus?.();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function createHamburgerButton() {
|
||||
const button = document.createElement('button');
|
||||
button.className = 'hamburger';
|
||||
button.setAttribute('aria-label', 'Menu de navegação');
|
||||
button.setAttribute('aria-expanded', 'false');
|
||||
button.innerHTML = `
|
||||
<div class="hamburger-icon">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
`;
|
||||
return button;
|
||||
}
|
||||
|
||||
// Auto-initialize if loaded as module
|
||||
if (typeof window !== 'undefined') {
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initMobileMenu);
|
||||
} else {
|
||||
initMobileMenu();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user