feat: page transitions, scroll progress bar, and staggered value cards
This commit is contained in:
@@ -42,7 +42,11 @@ const {
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</head>
|
||||
<body>
|
||||
<body class="page-ready">
|
||||
|
||||
<!-- Scroll progress bar -->
|
||||
<div class="scroll-progress" id="scrollProgress" role="progressbar" aria-label="Progreso de lectura" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
|
||||
<SiteHeader activeNav={activeNav} />
|
||||
<main>
|
||||
<slot />
|
||||
@@ -68,17 +72,49 @@ const {
|
||||
{ threshold: 0.1, rootMargin: '0px 0px -48px 0px' }
|
||||
);
|
||||
|
||||
document.querySelectorAll('.reveal, .reveal-left, .reveal-scale, .gold-line, .section-eyebrow').forEach((el) => {
|
||||
document.querySelectorAll('.reveal, .reveal-left, .reveal-scale, .gold-line, .section-eyebrow, .value-card-animate').forEach((el) => {
|
||||
io.observe(el);
|
||||
});
|
||||
}
|
||||
|
||||
// ─── HEADER SCROLL ELEVATION ─────────────────
|
||||
const header = document.querySelector('.site-header') as HTMLElement | null;
|
||||
if (header) {
|
||||
window.addEventListener('scroll', () => {
|
||||
header.classList.toggle('is-scrolled', window.scrollY > 16);
|
||||
}, { passive: true });
|
||||
// ─── SCROLL PROGRESS ────────────────────────
|
||||
const progressBar = document.getElementById('scrollProgress') as HTMLElement | null;
|
||||
if (progressBar) {
|
||||
const updateProgress = () => {
|
||||
const scrollTop = window.scrollY;
|
||||
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
|
||||
const progress = docHeight > 0 ? (scrollTop / docHeight) * 100 : 0;
|
||||
progressBar.style.width = `${progress}%`;
|
||||
progressBar.setAttribute('aria-valuenow', String(Math.round(progress)));
|
||||
};
|
||||
window.addEventListener('scroll', updateProgress, { passive: true });
|
||||
updateProgress();
|
||||
}
|
||||
|
||||
// ─── PAGE TRANSITIONS ───────────────────────
|
||||
// Fade IN: page loads → body gets .page-ready → CSS handles fade-in
|
||||
document.body.classList.add('page-ready');
|
||||
|
||||
// Fade OUT: intercept internal navigation links
|
||||
const handleNavClick = (e: MouseEvent) => {
|
||||
const target = e.target as HTMLElement;
|
||||
const anchor = target.closest('a');
|
||||
if (!anchor) return;
|
||||
|
||||
const href = anchor.getAttribute('href');
|
||||
if (!href || href.startsWith('#') || href.startsWith('http') || href.startsWith('mailto') || href.startsWith('tel') || anchor.target === '_blank') return;
|
||||
|
||||
e.preventDefault();
|
||||
document.body.classList.remove('page-ready');
|
||||
setTimeout(() => {
|
||||
window.location.href = href;
|
||||
}, 300);
|
||||
};
|
||||
|
||||
document.addEventListener('click', handleNavClick);
|
||||
|
||||
} else {
|
||||
// Reduced motion: show immediately, no transitions
|
||||
document.body.classList.add('page-ready');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user