Initial commit SteelBase - Oficiais e Funcionando

This commit is contained in:
Marcos
2026-03-22 16:56:47 -03:00
commit f10278909b
194 changed files with 87242 additions and 0 deletions

127
js/ui/mobile-menu.js Normal file
View 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();
}
}