initial commit
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
/* ============================================================
|
||||
LAYOUT.JS — shared across all layout pages
|
||||
Handles: theme switching, layout switching, mobile menu,
|
||||
FAQ accordion, contact form, scroll animations
|
||||
============================================================ */
|
||||
|
||||
(function () {
|
||||
|
||||
const html = document.documentElement;
|
||||
|
||||
// ── 1. Apply saved theme immediately (before paint) ──────
|
||||
const savedTheme = localStorage.getItem('demo-theme') || 'midnight';
|
||||
html.setAttribute('data-theme', savedTheme);
|
||||
|
||||
// ── 2. Apply saved layout pill active state ──────────────
|
||||
const savedLayout = localStorage.getItem('demo-layout') || 'a';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
// ── Theme switcher ──────────────────────────────────────
|
||||
const themePills = document.querySelectorAll('.theme-pill');
|
||||
|
||||
themePills.forEach(pill => {
|
||||
if (pill.dataset.t === savedTheme) pill.classList.add('active');
|
||||
pill.addEventListener('click', () => applyTheme(pill.dataset.t));
|
||||
});
|
||||
|
||||
function applyTheme(name) {
|
||||
html.setAttribute('data-theme', name);
|
||||
localStorage.setItem('demo-theme', name);
|
||||
themePills.forEach(p => p.classList.toggle('active', p.dataset.t === name));
|
||||
}
|
||||
|
||||
// ── Layout switcher ─────────────────────────────────────
|
||||
const layoutPills = document.querySelectorAll('.layout-pill');
|
||||
const LAYOUT_PAGES = { a: 'index.html', b: 'layout-b.html', c: 'layout-c.html' };
|
||||
|
||||
layoutPills.forEach(pill => {
|
||||
if (pill.dataset.l === savedLayout) pill.classList.add('active');
|
||||
|
||||
pill.addEventListener('click', () => {
|
||||
const target = pill.dataset.l;
|
||||
if (target === savedLayout) return; // already on this layout
|
||||
localStorage.setItem('demo-layout', target);
|
||||
|
||||
// Fade out, navigate
|
||||
document.body.style.transition = 'opacity 0.25s ease';
|
||||
document.body.style.opacity = '0';
|
||||
setTimeout(() => {
|
||||
window.location.href = LAYOUT_PAGES[target];
|
||||
}, 240);
|
||||
});
|
||||
});
|
||||
|
||||
// ── Mobile menu toggle ──────────────────────────────────
|
||||
const mobileToggle = document.getElementById('mobileToggle');
|
||||
const mobileMenu = document.getElementById('mobileMenu');
|
||||
if (mobileToggle) {
|
||||
mobileToggle.addEventListener('click', () => {
|
||||
mobileMenu.classList.toggle('is-open');
|
||||
});
|
||||
}
|
||||
|
||||
// ── FAQ accordion ───────────────────────────────────────
|
||||
document.querySelectorAll('.faq-question').forEach(btn => {
|
||||
btn.addEventListener('click', () => {
|
||||
const item = btn.closest('.faq-item');
|
||||
const isOpen = item.classList.contains('is-open');
|
||||
document.querySelectorAll('.faq-item').forEach(i => i.classList.remove('is-open'));
|
||||
if (!isOpen) item.classList.add('is-open');
|
||||
});
|
||||
});
|
||||
|
||||
// ── Contact form ────────────────────────────────────────
|
||||
const contactForm = document.getElementById('contactForm');
|
||||
const formSuccess = document.getElementById('formSuccess');
|
||||
if (contactForm) {
|
||||
contactForm.addEventListener('submit', e => {
|
||||
e.preventDefault();
|
||||
contactForm.style.display = 'none';
|
||||
formSuccess.classList.add('is-visible');
|
||||
});
|
||||
}
|
||||
|
||||
// ── Scroll-triggered feature cards ──────────────────────
|
||||
const featureCards = document.querySelectorAll('.feature-card');
|
||||
const observer = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
entry.target.style.opacity = '1';
|
||||
entry.target.style.transform = 'translateY(0)';
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
});
|
||||
}, { threshold: 0.12 });
|
||||
|
||||
featureCards.forEach((card, i) => {
|
||||
card.style.opacity = '0';
|
||||
card.style.transform = 'translateY(24px)';
|
||||
card.style.transition = `opacity 0.5s ease ${i * 0.08}s, transform 0.5s ease ${i * 0.08}s, border-color 0.3s ease, box-shadow 0.3s ease`;
|
||||
observer.observe(card);
|
||||
});
|
||||
|
||||
// ── Fade in on load ─────────────────────────────────────
|
||||
document.body.style.opacity = '0';
|
||||
document.body.style.transition = 'opacity 0.3s ease';
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => { document.body.style.opacity = '1'; });
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
Reference in New Issue
Block a user