The dark/white mode functionality has been fixed for deployment with Coolify using Nixpacks. The improvements include:

Early theme initialization to prevent flashing
Proper component and script loading order
Enhanced error handling and fallbacks
Better theme state persistence
System theme preference detection
The theme system will now work correctly in the production environment when deployed through Coolify with Nixpacks build pack.
This commit is contained in:
ben7sys
2024-11-15 10:15:18 +01:00
parent 263d2a88d6
commit 934aac41dc
19 changed files with 1197 additions and 82 deletions

View File

@@ -1,3 +1,6 @@
// Custom event for when components are fully loaded
const COMPONENTS_LOADED_EVENT = 'componentsLoaded';
document.addEventListener('DOMContentLoaded', function() {
// Helper function to handle component loading
async function loadComponent(url, insertPosition) {
@@ -11,8 +14,10 @@ document.addEventListener('DOMContentLoaded', function() {
if (url.includes('header.html')) {
initializeHeader();
}
return true;
} catch (error) {
console.warn(`Failed to load component from ${url}:`, error);
return false;
}
}
@@ -20,13 +25,20 @@ document.addEventListener('DOMContentLoaded', function() {
Promise.all([
loadComponent('components/header.html', 'afterbegin'),
loadComponent('components/footer.html', 'beforeend')
]).catch(error => {
]).then(results => {
if (results.every(Boolean)) {
// Dispatch custom event when all components are loaded
document.dispatchEvent(new CustomEvent(COMPONENTS_LOADED_EVENT));
}
}).catch(error => {
console.warn('Error loading components:', error);
});
// Initialize header functionality after it's loaded
function initializeHeader() {
const header = document.querySelector('header');
if (!header) return;
const mobileMenuToggle = header.querySelector('.mobile-menu-toggle');
const navMenu = header.querySelector('.nav-menu');
@@ -35,9 +47,11 @@ document.addEventListener('DOMContentLoaded', function() {
mobileMenuToggle.addEventListener('click', () => {
navMenu.classList.toggle('active');
const menuIcon = mobileMenuToggle.querySelector('i');
menuIcon.className = navMenu.classList.contains('active')
? 'fas fa-times'
: 'fas fa-bars';
if (menuIcon) {
menuIcon.className = navMenu.classList.contains('active')
? 'fas fa-times'
: 'fas fa-bars';
}
});
// Close menu when clicking outside
@@ -46,30 +60,41 @@ document.addEventListener('DOMContentLoaded', function() {
!e.target.closest('.nav-menu') &&
!e.target.closest('.mobile-menu-toggle')) {
navMenu.classList.remove('active');
mobileMenuToggle.querySelector('i').className = 'fas fa-bars';
const menuIcon = mobileMenuToggle.querySelector('i');
if (menuIcon) {
menuIcon.className = 'fas fa-bars';
}
}
});
}
// Scroll behavior
let lastScrollTop = 0;
let scrollTimeout;
window.addEventListener('scroll', () => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
// Don't hide header when near top of page
if (scrollTop < 100) {
header.style.transform = 'translateY(0)';
return;
if (scrollTimeout) {
window.cancelAnimationFrame(scrollTimeout);
}
// Hide header on scroll down, show on scroll up
if (scrollTop > lastScrollTop) {
header.style.transform = 'translateY(-100%)';
} else {
header.style.transform = 'translateY(0)';
}
lastScrollTop = scrollTop;
scrollTimeout = window.requestAnimationFrame(() => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
// Don't hide header when near top of page
if (scrollTop < 100) {
header.style.transform = 'translateY(0)';
return;
}
// Hide header on scroll down, show on scroll up
if (scrollTop > lastScrollTop) {
header.style.transform = 'translateY(-100%)';
} else {
header.style.transform = 'translateY(0)';
}
lastScrollTop = scrollTop;
});
}, { passive: true });
}
});