Implement feature X to enhance user experience and optimize performance

This commit is contained in:
2025-12-23 10:10:50 -05:00
parent dd58b714cd
commit 47aff75028

View File

@@ -1,4 +1,52 @@
<div class="min-h-screen overflow-hidden homepage-wrapper"> <div class="homepage-wrapper fullpage-slider" id="fullpageSlider">
<!-- Fixed Sidebar Navigation -->
<nav class="slider-nav fixed right-6 top-1/2 -translate-y-1/2 z-50 flex flex-col items-center gap-3">
<!-- Navigation Dots -->
<div class="nav-dots flex flex-col gap-2 bg-background-secondary/90 backdrop-blur-xl border border-neutral/30 rounded-full p-2 shadow-2xl">
<button type="button" class="nav-dot group relative" data-section="0" data-name="Hero" aria-label="Go to Hero section">
<span class="block w-3 h-3 rounded-full bg-primary transition-all duration-300 scale-125"></span>
<span class="nav-label absolute right-full mr-3 top-1/2 -translate-y-1/2 px-3 py-1.5 bg-background-secondary/95 backdrop-blur-sm border border-neutral/30 rounded-lg text-sm font-medium text-color-base whitespace-nowrap opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none shadow-lg">Hero</span>
</button>
<button type="button" class="nav-dot group relative" data-section="1" data-name="Services" aria-label="Go to Services section">
<span class="block w-3 h-3 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300"></span>
<span class="nav-label absolute right-full mr-3 top-1/2 -translate-y-1/2 px-3 py-1.5 bg-background-secondary/95 backdrop-blur-sm border border-neutral/30 rounded-lg text-sm font-medium text-color-base whitespace-nowrap opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none shadow-lg">Services</span>
</button>
<button type="button" class="nav-dot group relative" data-section="2" data-name="Control Panel" aria-label="Go to Control Panel section">
<span class="block w-3 h-3 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300"></span>
<span class="nav-label absolute right-full mr-3 top-1/2 -translate-y-1/2 px-3 py-1.5 bg-background-secondary/95 backdrop-blur-sm border border-neutral/30 rounded-lg text-sm font-medium text-color-base whitespace-nowrap opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none shadow-lg">Control Panel</span>
</button>
<button type="button" class="nav-dot group relative" data-section="3" data-name="Infrastructure" aria-label="Go to Infrastructure section">
<span class="block w-3 h-3 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300"></span>
<span class="nav-label absolute right-full mr-3 top-1/2 -translate-y-1/2 px-3 py-1.5 bg-background-secondary/95 backdrop-blur-sm border border-neutral/30 rounded-lg text-sm font-medium text-color-base whitespace-nowrap opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none shadow-lg">Infrastructure</span>
</button>
<button type="button" class="nav-dot group relative" data-section="4" data-name="Get Started" aria-label="Go to Get Started section">
<span class="block w-3 h-3 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300"></span>
<span class="nav-label absolute right-full mr-3 top-1/2 -translate-y-1/2 px-3 py-1.5 bg-background-secondary/95 backdrop-blur-sm border border-neutral/30 rounded-lg text-sm font-medium text-color-base whitespace-nowrap opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none shadow-lg">Get Started</span>
</button>
</div>
<!-- Arrow Navigation -->
<div class="nav-arrows flex flex-col gap-2 mt-4">
<button type="button" class="nav-arrow nav-prev p-2 rounded-full bg-background-secondary/90 backdrop-blur-xl border border-neutral/30 hover:border-primary/50 hover:bg-primary/20 transition-all duration-300 shadow-lg group" aria-label="Previous section">
<x-ri-arrow-up-s-line class="size-5 text-color-muted group-hover:text-primary transition-colors" />
</button>
<button type="button" class="nav-arrow nav-next p-2 rounded-full bg-background-secondary/90 backdrop-blur-xl border border-neutral/30 hover:border-primary/50 hover:bg-primary/20 transition-all duration-300 shadow-lg group" aria-label="Next section">
<x-ri-arrow-down-s-line class="size-5 text-color-muted group-hover:text-primary transition-colors" />
</button>
</div>
<!-- Section Counter -->
<div class="section-counter mt-4 px-3 py-2 bg-background-secondary/90 backdrop-blur-xl border border-neutral/30 rounded-full shadow-lg">
<span class="current-section text-primary font-bold">1</span>
<span class="text-color-muted">/</span>
<span class="total-sections text-color-muted">5</span>
</div>
</nav>
<!-- Slides Container -->
<div class="slides-container">
<!-- Slide 1: Hero -->
<div class="slide active" data-slide="0" id="hero">
<!-- Homepage-specific custom HTML --> <!-- Homepage-specific custom HTML -->
@if(theme('custom_homepage_html')) @if(theme('custom_homepage_html'))
<div class="custom-homepage-content"> <div class="custom-homepage-content">
@@ -7,7 +55,7 @@
@endif @endif
<!-- Hero Section - Asymmetric Modern Design --> <!-- Hero Section - Asymmetric Modern Design -->
<section class="relative min-h-[90vh] flex items-center"> <div class="slide-content relative min-h-screen flex items-center">
<!-- Ambient Background Effects --> <!-- Ambient Background Effects -->
<div class="absolute inset-0 overflow-hidden pointer-events-none"> <div class="absolute inset-0 overflow-hidden pointer-events-none">
<div class="absolute -top-40 -right-40 w-96 h-96 bg-primary/20 rounded-full blur-3xl animate-pulse"></div> <div class="absolute -top-40 -right-40 w-96 h-96 bg-primary/20 rounded-full blur-3xl animate-pulse"></div>
@@ -140,37 +188,12 @@
</div> </div>
</div> </div>
</div> </div>
</section>
<!-- Section Slider Navigation 1 -->
<div class="section-slider container mx-auto px-4 py-12" data-slider-index="0">
<div class="flex items-center justify-center gap-6">
<button type="button" class="slider-nav-btn slider-prev p-3 rounded-full bg-background-secondary/80 hover:bg-primary/20 border border-neutral/30 hover:border-primary/40 transition-all duration-300 group" aria-label="Previous section">
<x-ri-arrow-left-s-line class="size-5 text-color-muted group-hover:text-primary transition-colors" />
</button>
<div class="flex-1 max-w-md">
<div class="relative h-1 bg-neutral/20 rounded-full overflow-hidden">
<div class="slider-progress absolute left-0 top-0 h-full bg-gradient-to-r from-primary to-secondary rounded-full transition-all duration-300" style="width: 0%"></div>
</div>
<div class="flex justify-between mt-3">
<div class="slider-dots flex items-center gap-2">
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-primary transition-all duration-300" data-section="hero" aria-label="Go to Hero section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="services" aria-label="Go to Services section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="panel-features" aria-label="Go to Panel Features section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="features" aria-label="Go to Features section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="cta" aria-label="Go to CTA section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="footer" aria-label="Go to Footer section"></button>
</div>
</div>
</div>
<button type="button" class="slider-nav-btn slider-next p-3 rounded-full bg-background-secondary/80 hover:bg-primary/20 border border-neutral/30 hover:border-primary/40 transition-all duration-300 group" aria-label="Next section">
<x-ri-arrow-right-s-line class="size-5 text-color-muted group-hover:text-primary transition-colors" />
</button>
</div> </div>
</div> </div>
<!-- Services Section - Card Carousel Style --> <!-- Slide 2: Services -->
<section id="services" class="py-12 md:py-16"> <div class="slide" data-slide="1" id="services">
<div class="slide-content min-h-screen flex items-center py-20">
<div class="container mx-auto px-4"> <div class="container mx-auto px-4">
<div class="bg-gradient-to-b from-background-secondary/50 to-background-secondary/20 rounded-3xl p-8 md:p-12"> <div class="bg-gradient-to-b from-background-secondary/50 to-background-secondary/20 rounded-3xl p-8 md:p-12">
<div class="flex flex-col lg:flex-row lg:items-end lg:justify-between gap-6 mb-12"> <div class="flex flex-col lg:flex-row lg:items-end lg:justify-between gap-6 mb-12">
@@ -216,37 +239,12 @@
</div> </div>
</div> </div>
</div> </div>
</section>
<!-- Section Slider Navigation 2 -->
<div class="section-slider container mx-auto px-4 py-12" data-slider-index="1">
<div class="flex items-center justify-center gap-6">
<button type="button" class="slider-nav-btn slider-prev p-3 rounded-full bg-background-secondary/80 hover:bg-primary/20 border border-neutral/30 hover:border-primary/40 transition-all duration-300 group" aria-label="Previous section">
<x-ri-arrow-left-s-line class="size-5 text-color-muted group-hover:text-primary transition-colors" />
</button>
<div class="flex-1 max-w-md">
<div class="relative h-1 bg-neutral/20 rounded-full overflow-hidden">
<div class="slider-progress absolute left-0 top-0 h-full bg-gradient-to-r from-primary to-secondary rounded-full transition-all duration-300" style="width: 20%"></div>
</div>
<div class="flex justify-between mt-3">
<div class="slider-dots flex items-center gap-2">
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="hero" aria-label="Go to Hero section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-primary transition-all duration-300" data-section="services" aria-label="Go to Services section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="panel-features" aria-label="Go to Panel Features section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="features" aria-label="Go to Features section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="cta" aria-label="Go to CTA section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="footer" aria-label="Go to Footer section"></button>
</div>
</div>
</div>
<button type="button" class="slider-nav-btn slider-next p-3 rounded-full bg-background-secondary/80 hover:bg-primary/20 border border-neutral/30 hover:border-primary/40 transition-all duration-300 group" aria-label="Next section">
<x-ri-arrow-right-s-line class="size-5 text-color-muted group-hover:text-primary transition-colors" />
</button>
</div> </div>
</div> </div>
<!-- Control Panel Features - Modern Bento Layout --> <!-- Slide 3: Control Panel Features -->
<section id="panel-features" class="py-12 md:py-16 relative"> <div class="slide" data-slide="2" id="panel-features">
<div class="slide-content min-h-screen flex items-center py-20">
<div class="container mx-auto px-4"> <div class="container mx-auto px-4">
<div class="bg-gradient-to-b from-background-secondary/50 to-background-secondary/20 rounded-3xl p-8 md:p-12"> <div class="bg-gradient-to-b from-background-secondary/50 to-background-secondary/20 rounded-3xl p-8 md:p-12">
<!-- Section Header --> <!-- Section Header -->
@@ -604,37 +602,12 @@
</div> </div>
</div> </div>
</div> </div>
</section>
<!-- Section Slider Navigation 3 -->
<div class="section-slider container mx-auto px-4 py-12" data-slider-index="2">
<div class="flex items-center justify-center gap-6">
<button type="button" class="slider-nav-btn slider-prev p-3 rounded-full bg-background-secondary/80 hover:bg-primary/20 border border-neutral/30 hover:border-primary/40 transition-all duration-300 group" aria-label="Previous section">
<x-ri-arrow-left-s-line class="size-5 text-color-muted group-hover:text-primary transition-colors" />
</button>
<div class="flex-1 max-w-md">
<div class="relative h-1 bg-neutral/20 rounded-full overflow-hidden">
<div class="slider-progress absolute left-0 top-0 h-full bg-gradient-to-r from-primary to-secondary rounded-full transition-all duration-300" style="width: 40%"></div>
</div>
<div class="flex justify-between mt-3">
<div class="slider-dots flex items-center gap-2">
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="hero" aria-label="Go to Hero section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="services" aria-label="Go to Services section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-primary transition-all duration-300" data-section="panel-features" aria-label="Go to Panel Features section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="features" aria-label="Go to Features section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="cta" aria-label="Go to CTA section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="footer" aria-label="Go to Footer section"></button>
</div>
</div>
</div>
<button type="button" class="slider-nav-btn slider-next p-3 rounded-full bg-background-secondary/80 hover:bg-primary/20 border border-neutral/30 hover:border-primary/40 transition-all duration-300 group" aria-label="Next section">
<x-ri-arrow-right-s-line class="size-5 text-color-muted group-hover:text-primary transition-colors" />
</button>
</div> </div>
</div> </div>
<!-- Infrastructure Features --> <!-- Slide 4: Infrastructure Features -->
<section id="features" class="py-12 md:py-16"> <div class="slide" data-slide="3" id="features">
<div class="slide-content min-h-screen flex items-center py-20">
<div class="container mx-auto px-4"> <div class="container mx-auto px-4">
<div class="bg-gradient-to-b from-background-secondary/50 to-background-secondary/20 rounded-3xl p-8 md:p-12"> <div class="bg-gradient-to-b from-background-secondary/50 to-background-secondary/20 rounded-3xl p-8 md:p-12">
<!-- Section Header --> <!-- Section Header -->
@@ -744,37 +717,12 @@
</div> </div>
</div> </div>
</div> </div>
</section>
<!-- Section Slider Navigation 4 -->
<div class="section-slider container mx-auto px-4 py-12" data-slider-index="3">
<div class="flex items-center justify-center gap-6">
<button type="button" class="slider-nav-btn slider-prev p-3 rounded-full bg-background-secondary/80 hover:bg-primary/20 border border-neutral/30 hover:border-primary/40 transition-all duration-300 group" aria-label="Previous section">
<x-ri-arrow-left-s-line class="size-5 text-color-muted group-hover:text-primary transition-colors" />
</button>
<div class="flex-1 max-w-md">
<div class="relative h-1 bg-neutral/20 rounded-full overflow-hidden">
<div class="slider-progress absolute left-0 top-0 h-full bg-gradient-to-r from-primary to-secondary rounded-full transition-all duration-300" style="width: 60%"></div>
</div>
<div class="flex justify-between mt-3">
<div class="slider-dots flex items-center gap-2">
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="hero" aria-label="Go to Hero section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="services" aria-label="Go to Services section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="panel-features" aria-label="Go to Panel Features section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-primary transition-all duration-300" data-section="features" aria-label="Go to Features section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="cta" aria-label="Go to CTA section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="footer" aria-label="Go to Footer section"></button>
</div>
</div>
</div>
<button type="button" class="slider-nav-btn slider-next p-3 rounded-full bg-background-secondary/80 hover:bg-primary/20 border border-neutral/30 hover:border-primary/40 transition-all duration-300 group" aria-label="Next section">
<x-ri-arrow-right-s-line class="size-5 text-color-muted group-hover:text-primary transition-colors" />
</button>
</div> </div>
</div> </div>
<!-- CTA Section - Modern Split Design --> <!-- Slide 5: CTA Section -->
<section id="cta" class="py-12 md:py-16"> <div class="slide" data-slide="4" id="cta">
<div class="slide-content min-h-screen flex items-center py-20">
<div class="container mx-auto px-4"> <div class="container mx-auto px-4">
<div class="relative overflow-hidden bg-gradient-to-br from-background-secondary to-background-secondary/80 border border-neutral/30 rounded-3xl"> <div class="relative overflow-hidden bg-gradient-to-br from-background-secondary to-background-secondary/80 border border-neutral/30 rounded-3xl">
<div class="grid lg:grid-cols-2 gap-0"> <div class="grid lg:grid-cols-2 gap-0">
@@ -888,41 +836,75 @@
</div> </div>
</div> </div>
</div> </div>
</section>
<!-- Section Slider Navigation 5 -->
<div class="section-slider container mx-auto px-4 py-12" data-slider-index="4">
<div class="flex items-center justify-center gap-6">
<button type="button" class="slider-nav-btn slider-prev p-3 rounded-full bg-background-secondary/80 hover:bg-primary/20 border border-neutral/30 hover:border-primary/40 transition-all duration-300 group" aria-label="Previous section">
<x-ri-arrow-left-s-line class="size-5 text-color-muted group-hover:text-primary transition-colors" />
</button>
<div class="flex-1 max-w-md">
<div class="relative h-1 bg-neutral/20 rounded-full overflow-hidden">
<div class="slider-progress absolute left-0 top-0 h-full bg-gradient-to-r from-primary to-secondary rounded-full transition-all duration-300" style="width: 80%"></div>
</div>
<div class="flex justify-between mt-3">
<div class="slider-dots flex items-center gap-2">
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="hero" aria-label="Go to Hero section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="services" aria-label="Go to Services section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="panel-features" aria-label="Go to Panel Features section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="features" aria-label="Go to Features section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-primary transition-all duration-300" data-section="cta" aria-label="Go to CTA section"></button>
<button type="button" class="slider-dot w-2 h-2 rounded-full bg-neutral/40 hover:bg-primary/60 transition-all duration-300" data-section="footer" aria-label="Go to Footer section"></button>
</div>
</div>
</div>
<button type="button" class="slider-nav-btn slider-next p-3 rounded-full bg-background-secondary/80 hover:bg-primary/20 border border-neutral/30 hover:border-primary/40 transition-all duration-300 group" aria-label="Next section">
<x-ri-arrow-right-s-line class="size-5 text-color-muted group-hover:text-primary transition-colors" />
</button>
</div>
</div> </div>
<div class="pb-8"> </div><!-- End slides-container -->
<!-- Hook Content -->
<div class="hook-content fixed bottom-0 left-0 right-0 z-40 pointer-events-none">
<div class="pb-8 pointer-events-auto">
{!! hook('pages.home') !!} {!! hook('pages.home') !!}
</div> </div>
</div> </div>
</div>
<style> <style>
/* Fullpage Slider Styles */
.fullpage-slider {
height: 100vh;
overflow: hidden;
position: relative;
}
.slides-container {
height: 100vh;
position: relative;
}
.slide {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100vh;
opacity: 0;
visibility: hidden;
transition: opacity 0.6s ease, visibility 0.6s ease, transform 0.6s ease;
transform: translateY(20px);
overflow-y: auto;
overflow-x: hidden;
}
.slide.active {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.slide.slide-up {
transform: translateY(-20px);
}
.slide-content {
min-height: 100vh;
display: flex;
align-items: center;
}
/* Navigation Styles */
.slider-nav {
z-index: 100;
}
.nav-dot span:first-child {
transition: all 0.3s ease;
}
.nav-dot.active span:first-child {
background-color: rgb(var(--color-primary)) !important;
transform: scale(1.25);
}
/* Custom Color Palette */ /* Custom Color Palette */
:root { :root {
--hp-lime-light: #D9ED92; --hp-lime-light: #D9ED92;
@@ -1113,117 +1095,99 @@
<script> <script>
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
// Section slider configuration // Fullpage Slider Configuration
const sections = ['hero', 'services', 'panel-features', 'features', 'cta', 'footer']; const slides = document.querySelectorAll('.slide');
let currentSectionIndex = 0; const navDots = document.querySelectorAll('.nav-dot');
const prevBtn = document.querySelector('.nav-prev');
const nextBtn = document.querySelector('.nav-next');
const currentSectionEl = document.querySelector('.current-section');
const totalSectionsEl = document.querySelector('.total-sections');
const sectionIds = ['hero', 'services', 'panel-features', 'features', 'cta'];
let currentSlide = 0;
let isAnimating = false;
let autoSlideInterval = null; let autoSlideInterval = null;
let isManuallyInterrupted = false; let isManuallyInterrupted = false;
const AUTO_SLIDE_DELAY = 10000; // 10 seconds const AUTO_SLIDE_DELAY = 10000; // 10 seconds
const RESUME_DELAY = 30000; // Resume auto-slide after 30 seconds of no interaction const RESUME_DELAY = 30000; // Resume auto-slide after 30 seconds of inactivity
let resumeTimeout = null; let resumeTimeout = null;
const ANIMATION_DURATION = 600; // Match CSS transition duration
// Get all slider elements // Initialize
const sliders = document.querySelectorAll('.section-slider'); totalSectionsEl.textContent = slides.length;
// Function to scroll to a section // Function to go to a specific slide
function scrollToSection(sectionId) { function goToSlide(index, direction = 'next') {
let targetElement; if (isAnimating || index === currentSlide || index < 0 || index >= slides.length) return;
if (sectionId === 'hero') {
// Scroll to top for hero isAnimating = true;
window.scrollTo({ top: 0, behavior: 'smooth' });
return; const currentSlideEl = slides[currentSlide];
} else if (sectionId === 'footer') { const nextSlideEl = slides[index];
// Scroll to bottom for footer
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' }); // Add direction class for animation
return; if (direction === 'prev') {
currentSlideEl.classList.add('slide-up');
}
// Deactivate current slide
currentSlideEl.classList.remove('active');
// Activate new slide
nextSlideEl.classList.add('active');
// Update navigation dots
navDots.forEach((dot, i) => {
const dotSpan = dot.querySelector('span:first-child');
if (i === index) {
dot.classList.add('active');
dotSpan.classList.remove('bg-neutral/40');
dotSpan.classList.add('bg-primary');
dotSpan.style.transform = 'scale(1.25)';
} else { } else {
targetElement = document.getElementById(sectionId); dot.classList.remove('active');
dotSpan.classList.remove('bg-primary');
dotSpan.classList.add('bg-neutral/40');
dotSpan.style.transform = 'scale(1)';
} }
if (targetElement) {
const headerOffset = 100; // Account for fixed header if any
const elementPosition = targetElement.getBoundingClientRect().top;
const offsetPosition = elementPosition + window.pageYOffset - headerOffset;
window.scrollTo({
top: offsetPosition,
behavior: 'smooth'
}); });
}
}
// Function to update all slider UI elements // Update section counter
function updateAllSliderUI(activeIndex) { currentSectionEl.textContent = index + 1;
sliders.forEach(slider => {
const dots = slider.querySelectorAll('.slider-dot');
const progressBar = slider.querySelector('.slider-progress');
// Update dots // Update URL hash without triggering scroll
dots.forEach((dot, index) => { const sectionId = sectionIds[index];
if (index === activeIndex) { if (sectionId && sectionId !== 'hero') {
dot.classList.remove('bg-neutral/40'); history.replaceState(null, null, '#' + sectionId);
dot.classList.add('bg-primary');
} else { } else {
dot.classList.remove('bg-primary'); history.replaceState(null, null, window.location.pathname);
dot.classList.add('bg-neutral/40');
}
});
// Update progress bar
if (progressBar) {
const progress = ((activeIndex) / (sections.length - 1)) * 100;
progressBar.style.width = progress + '%';
}
});
} }
// Function to determine current section based on scroll position currentSlide = index;
function getCurrentSectionFromScroll() {
const scrollPosition = window.scrollY + window.innerHeight / 2;
const documentHeight = document.documentElement.scrollHeight;
// Check if near bottom (footer) // Reset animation state after transition
if (window.scrollY + window.innerHeight >= documentHeight - 100) { setTimeout(() => {
return sections.length - 1; isAnimating = false;
currentSlideEl.classList.remove('slide-up');
}, ANIMATION_DURATION);
} }
// Check if at top (hero) // Function to go to next slide
if (window.scrollY < 200) { function goToNextSlide() {
return 0; const nextIndex = (currentSlide + 1) % slides.length;
goToSlide(nextIndex, 'next');
} }
// Find the current section // Function to go to previous slide
for (let i = sections.length - 2; i >= 1; i--) { function goToPrevSlide() {
const section = document.getElementById(sections[i]); const prevIndex = (currentSlide - 1 + slides.length) % slides.length;
if (section) { goToSlide(prevIndex, 'prev');
const rect = section.getBoundingClientRect();
if (rect.top <= window.innerHeight / 2) {
return i;
}
}
}
return 0;
}
// Function to go to next section
function goToNextSection() {
currentSectionIndex = (currentSectionIndex + 1) % sections.length;
scrollToSection(sections[currentSectionIndex]);
updateAllSliderUI(currentSectionIndex);
}
// Function to go to previous section
function goToPrevSection() {
currentSectionIndex = (currentSectionIndex - 1 + sections.length) % sections.length;
scrollToSection(sections[currentSectionIndex]);
updateAllSliderUI(currentSectionIndex);
} }
// Function to start auto-slide // Function to start auto-slide
function startAutoSlide() { function startAutoSlide() {
if (autoSlideInterval) clearInterval(autoSlideInterval); if (autoSlideInterval) clearInterval(autoSlideInterval);
autoSlideInterval = setInterval(goToNextSection, AUTO_SLIDE_DELAY); autoSlideInterval = setInterval(goToNextSlide, AUTO_SLIDE_DELAY);
} }
// Function to stop auto-slide // Function to stop auto-slide
@@ -1249,102 +1213,179 @@ document.addEventListener('DOMContentLoaded', function() {
}, RESUME_DELAY); }, RESUME_DELAY);
} }
// Add click handlers to all slider navigation buttons // Navigation dot click handlers
sliders.forEach(slider => { navDots.forEach((dot, index) => {
// Previous button dot.addEventListener('click', (e) => {
const prevBtn = slider.querySelector('.slider-prev'); e.preventDefault();
handleManualInteraction();
const direction = index > currentSlide ? 'next' : 'prev';
goToSlide(index, direction);
});
});
// Arrow button click handlers
if (prevBtn) { if (prevBtn) {
prevBtn.addEventListener('click', (e) => { prevBtn.addEventListener('click', (e) => {
e.preventDefault(); e.preventDefault();
handleManualInteraction(); handleManualInteraction();
goToPrevSection(); goToPrevSlide();
}); });
} }
// Next button
const nextBtn = slider.querySelector('.slider-next');
if (nextBtn) { if (nextBtn) {
nextBtn.addEventListener('click', (e) => { nextBtn.addEventListener('click', (e) => {
e.preventDefault(); e.preventDefault();
handleManualInteraction(); handleManualInteraction();
goToNextSection(); goToNextSlide();
}); });
} }
// Dot buttons // Scroll wheel navigation
const dots = slider.querySelectorAll('.slider-dot'); let scrollTimeout = null;
dots.forEach((dot, index) => { let lastScrollTime = 0;
dot.addEventListener('click', (e) => { const SCROLL_COOLDOWN = 800; // Prevent rapid scrolling
document.addEventListener('wheel', (e) => {
const now = Date.now();
if (now - lastScrollTime < SCROLL_COOLDOWN) return;
if (isAnimating) return;
// Check if we're inside a scrollable slide content
const slideContent = slides[currentSlide].querySelector('.slide-content');
if (slideContent) {
const scrollTop = slides[currentSlide].scrollTop;
const scrollHeight = slides[currentSlide].scrollHeight;
const clientHeight = slides[currentSlide].clientHeight;
// Allow internal scroll if content is scrollable
if (scrollHeight > clientHeight) {
// Scrolling down and not at bottom
if (e.deltaY > 0 && scrollTop + clientHeight < scrollHeight - 10) {
return;
}
// Scrolling up and not at top
if (e.deltaY < 0 && scrollTop > 10) {
return;
}
}
}
lastScrollTime = now;
handleManualInteraction();
if (e.deltaY > 0) {
// Scroll down - next slide
if (currentSlide < slides.length - 1) {
goToNextSlide();
}
} else {
// Scroll up - previous slide
if (currentSlide > 0) {
goToPrevSlide();
}
}
}, { passive: true });
// Keyboard navigation
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowDown' || e.key === 'ArrowRight') {
e.preventDefault(); e.preventDefault();
handleManualInteraction(); handleManualInteraction();
currentSectionIndex = index; goToNextSlide();
scrollToSection(sections[index]); } else if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') {
updateAllSliderUI(index); e.preventDefault();
}); handleManualInteraction();
}); goToPrevSlide();
}
}); });
// Update slider UI on scroll // Touch navigation for mobile
let scrollTimeout; let touchStartY = 0;
window.addEventListener('scroll', () => { let touchEndY = 0;
clearTimeout(scrollTimeout); const SWIPE_THRESHOLD = 50;
scrollTimeout = setTimeout(() => {
const newIndex = getCurrentSectionFromScroll(); document.addEventListener('touchstart', (e) => {
if (newIndex !== currentSectionIndex) { touchStartY = e.changedTouches[0].screenY;
currentSectionIndex = newIndex; }, { passive: true });
updateAllSliderUI(currentSectionIndex);
document.addEventListener('touchend', (e) => {
if (isAnimating) return;
touchEndY = e.changedTouches[0].screenY;
const diff = touchStartY - touchEndY;
if (Math.abs(diff) > SWIPE_THRESHOLD) {
handleManualInteraction();
if (diff > 0) {
// Swiped up - next slide
goToNextSlide();
} else {
// Swiped down - previous slide
goToPrevSlide();
} }
}, 100); }
}); }, { passive: true });
// Handle hash links (# links) // Handle hash links (# links)
function handleHashChange() { function handleHashChange() {
const hash = window.location.hash.substring(1); const hash = window.location.hash.substring(1);
if (hash) { if (hash) {
const sectionIndex = sections.indexOf(hash); const sectionIndex = sectionIds.indexOf(hash);
if (sectionIndex !== -1) { if (sectionIndex !== -1 && sectionIndex !== currentSlide) {
handleManualInteraction(); handleManualInteraction();
currentSectionIndex = sectionIndex; const direction = sectionIndex > currentSlide ? 'next' : 'prev';
updateAllSliderUI(currentSectionIndex); goToSlide(sectionIndex, direction);
} }
} }
} }
// Handle clicks on internal links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', (e) => {
const hash = anchor.getAttribute('href').substring(1);
const sectionIndex = sectionIds.indexOf(hash);
if (sectionIndex !== -1) {
e.preventDefault();
handleManualInteraction();
const direction = sectionIndex > currentSlide ? 'next' : 'prev';
goToSlide(sectionIndex, direction);
}
});
});
// Listen for hash changes // Listen for hash changes
window.addEventListener('hashchange', handleHashChange); window.addEventListener('hashchange', handleHashChange);
// Check initial hash // Check initial hash
if (window.location.hash) { if (window.location.hash) {
handleHashChange(); const hash = window.location.hash.substring(1);
} const sectionIndex = sectionIds.indexOf(hash);
if (sectionIndex !== -1) {
// Directly set without animation on initial load
slides[0].classList.remove('active');
slides[sectionIndex].classList.add('active');
currentSlide = sectionIndex;
currentSectionEl.textContent = sectionIndex + 1;
// Pause auto-slide when user interacts with page // Update nav dots
document.addEventListener('mousedown', () => { navDots.forEach((dot, i) => {
if (!isManuallyInterrupted) { const dotSpan = dot.querySelector('span:first-child');
handleManualInteraction(); if (i === sectionIndex) {
dot.classList.add('active');
dotSpan.classList.remove('bg-neutral/40');
dotSpan.classList.add('bg-primary');
dotSpan.style.transform = 'scale(1.25)';
} else {
dot.classList.remove('active');
dotSpan.classList.remove('bg-primary');
dotSpan.classList.add('bg-neutral/40');
dotSpan.style.transform = 'scale(1)';
} }
}); });
document.addEventListener('touchstart', () => {
if (!isManuallyInterrupted) {
handleManualInteraction();
} }
});
document.addEventListener('keydown', (e) => {
// Handle arrow key navigation
if (e.key === 'ArrowLeft') {
handleManualInteraction();
goToPrevSection();
} else if (e.key === 'ArrowRight') {
handleManualInteraction();
goToNextSection();
} }
});
// Initialize // Start auto-slide
currentSectionIndex = getCurrentSectionFromScroll();
updateAllSliderUI(currentSectionIndex);
startAutoSlide(); startAutoSlide();
}); });
</script> </script>