feat: implement section slider navigation for enhanced user experience across homepage sections

This commit is contained in:
2025-12-23 08:47:49 -05:00
parent 8f82084835
commit dd58b714cd

View File

@@ -142,16 +142,30 @@
</div>
</section>
<!-- Section Divider -->
<div class="container mx-auto px-4 py-16">
<div class="flex items-center justify-center gap-4">
<div class="flex-1 h-px bg-gradient-to-r from-transparent via-neutral/30 to-neutral/50"></div>
<div class="flex items-center gap-2">
<div class="w-2 h-2 rounded-full bg-primary/50"></div>
<div class="w-3 h-3 rounded-full bg-primary"></div>
<div class="w-2 h-2 rounded-full bg-primary/50"></div>
<!-- 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>
<div class="flex-1 h-px bg-gradient-to-l from-transparent via-neutral/30 to-neutral/50"></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>
@@ -204,16 +218,30 @@
</div>
</section>
<!-- Section Divider -->
<div class="container mx-auto px-4 py-16">
<div class="flex items-center justify-center gap-4">
<div class="flex-1 h-px bg-gradient-to-r from-transparent via-neutral/30 to-neutral/50"></div>
<div class="flex items-center gap-2">
<div class="w-2 h-2 rounded-full bg-primary/50"></div>
<div class="w-3 h-3 rounded-full bg-primary"></div>
<div class="w-2 h-2 rounded-full bg-primary/50"></div>
<!-- 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>
<div class="flex-1 h-px bg-gradient-to-l from-transparent via-neutral/30 to-neutral/50"></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>
@@ -578,16 +606,30 @@
</div>
</section>
<!-- Section Divider -->
<div class="container mx-auto px-4 py-16">
<div class="flex items-center justify-center gap-4">
<div class="flex-1 h-px bg-gradient-to-r from-transparent via-neutral/30 to-neutral/50"></div>
<div class="flex items-center gap-2">
<div class="w-2 h-2 rounded-full bg-primary/50"></div>
<div class="w-3 h-3 rounded-full bg-primary"></div>
<div class="w-2 h-2 rounded-full bg-primary/50"></div>
<!-- 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>
<div class="flex-1 h-px bg-gradient-to-l from-transparent via-neutral/30 to-neutral/50"></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>
@@ -704,21 +746,35 @@
</div>
</section>
<!-- Section Divider -->
<div class="container mx-auto px-4 py-16">
<div class="flex items-center justify-center gap-4">
<div class="flex-1 h-px bg-gradient-to-r from-transparent via-neutral/30 to-neutral/50"></div>
<div class="flex items-center gap-2">
<div class="w-2 h-2 rounded-full bg-primary/50"></div>
<div class="w-3 h-3 rounded-full bg-primary"></div>
<div class="w-2 h-2 rounded-full bg-primary/50"></div>
<!-- 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>
<div class="flex-1 h-px bg-gradient-to-l from-transparent via-neutral/30 to-neutral/50"></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>
<!-- CTA Section - Modern Split Design -->
<section class="py-12 md:py-16">
<section id="cta" class="py-12 md:py-16">
<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="grid lg:grid-cols-2 gap-0">
@@ -834,16 +890,30 @@
</div>
</section>
<!-- Section Divider -->
<div class="container mx-auto px-4 py-16">
<div class="flex items-center justify-center gap-4">
<div class="flex-1 h-px bg-gradient-to-r from-transparent via-neutral/30 to-neutral/50"></div>
<div class="flex items-center gap-2">
<div class="w-2 h-2 rounded-full bg-primary/50"></div>
<div class="w-3 h-3 rounded-full bg-primary"></div>
<div class="w-2 h-2 rounded-full bg-primary/50"></div>
<!-- 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>
<div class="flex-1 h-px bg-gradient-to-l from-transparent via-neutral/30 to-neutral/50"></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>
@@ -1040,3 +1110,241 @@
.homepage-wrapper .hover\:shadow-emerald-500\/30:hover { --tw-shadow-color: rgba(118, 200, 147, 0.3) !important; }
.homepage-wrapper .hover\:shadow-orange-500\/10:hover { --tw-shadow-color: rgba(82, 182, 154, 0.1) !important; }
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Section slider configuration
const sections = ['hero', 'services', 'panel-features', 'features', 'cta', 'footer'];
let currentSectionIndex = 0;
let autoSlideInterval = null;
let isManuallyInterrupted = false;
const AUTO_SLIDE_DELAY = 10000; // 10 seconds
const RESUME_DELAY = 30000; // Resume auto-slide after 30 seconds of no interaction
let resumeTimeout = null;
// Get all slider elements
const sliders = document.querySelectorAll('.section-slider');
// Function to scroll to a section
function scrollToSection(sectionId) {
let targetElement;
if (sectionId === 'hero') {
// Scroll to top for hero
window.scrollTo({ top: 0, behavior: 'smooth' });
return;
} else if (sectionId === 'footer') {
// Scroll to bottom for footer
window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth' });
return;
} else {
targetElement = document.getElementById(sectionId);
}
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
function updateAllSliderUI(activeIndex) {
sliders.forEach(slider => {
const dots = slider.querySelectorAll('.slider-dot');
const progressBar = slider.querySelector('.slider-progress');
// Update dots
dots.forEach((dot, index) => {
if (index === activeIndex) {
dot.classList.remove('bg-neutral/40');
dot.classList.add('bg-primary');
} else {
dot.classList.remove('bg-primary');
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
function getCurrentSectionFromScroll() {
const scrollPosition = window.scrollY + window.innerHeight / 2;
const documentHeight = document.documentElement.scrollHeight;
// Check if near bottom (footer)
if (window.scrollY + window.innerHeight >= documentHeight - 100) {
return sections.length - 1;
}
// Check if at top (hero)
if (window.scrollY < 200) {
return 0;
}
// Find the current section
for (let i = sections.length - 2; i >= 1; i--) {
const section = document.getElementById(sections[i]);
if (section) {
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 startAutoSlide() {
if (autoSlideInterval) clearInterval(autoSlideInterval);
autoSlideInterval = setInterval(goToNextSection, AUTO_SLIDE_DELAY);
}
// Function to stop auto-slide
function stopAutoSlide() {
if (autoSlideInterval) {
clearInterval(autoSlideInterval);
autoSlideInterval = null;
}
}
// Function to handle manual interruption
function handleManualInteraction() {
isManuallyInterrupted = true;
stopAutoSlide();
// Clear existing resume timeout
if (resumeTimeout) clearTimeout(resumeTimeout);
// Resume auto-slide after delay
resumeTimeout = setTimeout(() => {
isManuallyInterrupted = false;
startAutoSlide();
}, RESUME_DELAY);
}
// Add click handlers to all slider navigation buttons
sliders.forEach(slider => {
// Previous button
const prevBtn = slider.querySelector('.slider-prev');
if (prevBtn) {
prevBtn.addEventListener('click', (e) => {
e.preventDefault();
handleManualInteraction();
goToPrevSection();
});
}
// Next button
const nextBtn = slider.querySelector('.slider-next');
if (nextBtn) {
nextBtn.addEventListener('click', (e) => {
e.preventDefault();
handleManualInteraction();
goToNextSection();
});
}
// Dot buttons
const dots = slider.querySelectorAll('.slider-dot');
dots.forEach((dot, index) => {
dot.addEventListener('click', (e) => {
e.preventDefault();
handleManualInteraction();
currentSectionIndex = index;
scrollToSection(sections[index]);
updateAllSliderUI(index);
});
});
});
// Update slider UI on scroll
let scrollTimeout;
window.addEventListener('scroll', () => {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(() => {
const newIndex = getCurrentSectionFromScroll();
if (newIndex !== currentSectionIndex) {
currentSectionIndex = newIndex;
updateAllSliderUI(currentSectionIndex);
}
}, 100);
});
// Handle hash links (# links)
function handleHashChange() {
const hash = window.location.hash.substring(1);
if (hash) {
const sectionIndex = sections.indexOf(hash);
if (sectionIndex !== -1) {
handleManualInteraction();
currentSectionIndex = sectionIndex;
updateAllSliderUI(currentSectionIndex);
}
}
}
// Listen for hash changes
window.addEventListener('hashchange', handleHashChange);
// Check initial hash
if (window.location.hash) {
handleHashChange();
}
// Pause auto-slide when user interacts with page
document.addEventListener('mousedown', () => {
if (!isManuallyInterrupted) {
handleManualInteraction();
}
});
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
currentSectionIndex = getCurrentSectionFromScroll();
updateAllSliderUI(currentSectionIndex);
startAutoSlide();
});
</script>