Revert "Homepage fertig: Horizontales Scrollen, größere Sections, How-it-works überarbeitet"
This reverts commit e85add438f.
This commit is contained in:
@@ -1,11 +0,0 @@
|
||||
Homepage fertig: Horizontales Scrollen, größere Sections, How-it-works überarbeitet
|
||||
|
||||
Homepage abgeschlossen
|
||||
|
||||
- Horizontales Scrollen: Features, How it works, Pricing und FAQ in einem
|
||||
horizontalen Scroll-Container mit Snap, Tastatur- und Touch-Navigation
|
||||
- Zentrierung: Sections und Inhalte zentriert, overflow-x auf Body verhindert
|
||||
- Größen: Moderate Schrift- und Abstände in Features, Pricing, FAQ
|
||||
- How it works: Vergrößert (Titel 4xl–6xl, große Step-Cards, größere Icons und CTA)
|
||||
- Navbar: Links springen in die passende Horizontal-Section
|
||||
- Neue Komponente: HorizontalScrollNav (Dots), Hover-Pfeile, Scrollbar ausgeblendet
|
||||
@@ -1,60 +0,0 @@
|
||||
import React from 'react'
|
||||
|
||||
interface Section {
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
|
||||
interface HorizontalScrollNavProps {
|
||||
sections: Section[]
|
||||
activeIndex: number
|
||||
onNavigate: (index: number) => void
|
||||
}
|
||||
|
||||
export function HorizontalScrollNav({
|
||||
sections,
|
||||
activeIndex,
|
||||
onNavigate
|
||||
}: HorizontalScrollNavProps) {
|
||||
return (
|
||||
<>
|
||||
{/* Desktop - Vertical Dots rechts */}
|
||||
<div className="hidden md:flex fixed right-8 top-1/2 -translate-y-1/2 z-50 flex-col gap-4">
|
||||
{sections.map((section, index) => (
|
||||
<button
|
||||
key={section.id}
|
||||
onClick={() => onNavigate(index)}
|
||||
className={`
|
||||
transition-all duration-300 rounded-full
|
||||
${index === activeIndex
|
||||
? 'w-1.5 h-16 bg-primary-500 dark:bg-primary-400'
|
||||
: 'w-1 h-12 bg-slate-600 dark:bg-slate-500 hover:bg-slate-400 dark:hover:bg-slate-400'
|
||||
}
|
||||
`}
|
||||
title={section.name}
|
||||
aria-label={`Go to ${section.name}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Mobile - Horizontal Dots unten */}
|
||||
<div className="md:hidden fixed bottom-8 left-1/2 -translate-x-1/2 z-50 flex gap-3">
|
||||
{sections.map((section, index) => (
|
||||
<button
|
||||
key={section.id}
|
||||
onClick={() => onNavigate(index)}
|
||||
className={`
|
||||
transition-all duration-300 rounded-full
|
||||
${index === activeIndex
|
||||
? 'w-8 h-2 bg-primary-500 dark:bg-primary-400'
|
||||
: 'w-6 h-2 bg-slate-600 dark:bg-slate-500'
|
||||
}
|
||||
`}
|
||||
title={section.name}
|
||||
aria-label={`Go to ${section.name}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -14,24 +14,6 @@ export function Navbar() {
|
||||
const scrollToSection = useCallback((sectionId: string) => {
|
||||
setIsMenuOpen(false)
|
||||
|
||||
// Horizontal scroll sections
|
||||
const horizontalSections = ['features', 'how-it-works', 'pricing', 'faq']
|
||||
|
||||
if (horizontalSections.includes(sectionId)) {
|
||||
// Dispatch custom event for horizontal scroll
|
||||
const event = new CustomEvent('scrollToHorizontalSection', {
|
||||
detail: { sectionId }
|
||||
})
|
||||
window.dispatchEvent(event)
|
||||
|
||||
// If not on home page, navigate first
|
||||
if (location.pathname !== '/') {
|
||||
navigate('/')
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Vertical scroll for other sections
|
||||
// If not on home page, navigate first
|
||||
if (location.pathname !== '/') {
|
||||
navigate('/')
|
||||
|
||||
@@ -84,7 +84,6 @@
|
||||
/* Base styles */
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
overflow-x: hidden; /* Prevent horizontal scroll on body */
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -94,8 +93,6 @@ body {
|
||||
/* Improve touch scrolling on mobile */
|
||||
-webkit-overflow-scrolling: touch;
|
||||
overflow-scrolling: touch;
|
||||
/* Prevent horizontal scroll */
|
||||
overflow-x: hidden;
|
||||
/* Base colors - Tailwind will handle dark mode */
|
||||
background-color: var(--color-slate-50);
|
||||
color: var(--color-slate-900);
|
||||
@@ -327,38 +324,3 @@ body {
|
||||
html:not(.dark-mode-initialized) body {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
/* Horizontal Scroll Container Styles */
|
||||
/* Hide scrollbar but keep functionality */
|
||||
.scrollbar-hide {
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
|
||||
.scrollbar-hide::-webkit-scrollbar {
|
||||
display: none; /* Chrome, Safari, Opera */
|
||||
}
|
||||
|
||||
/* Snap scroll behavior */
|
||||
.snap-x {
|
||||
scroll-snap-type: x mandatory;
|
||||
}
|
||||
|
||||
.snap-center {
|
||||
scroll-snap-align: center;
|
||||
}
|
||||
|
||||
.snap-mandatory {
|
||||
scroll-snap-type: x mandatory;
|
||||
}
|
||||
|
||||
/* Smooth scrolling for horizontal containers */
|
||||
.scroll-smooth {
|
||||
scroll-behavior: smooth;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/* Ensure sections take full viewport width */
|
||||
.w-screen {
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
@@ -1,187 +1,25 @@
|
||||
import { useRef, useState, useEffect, useCallback } from 'react'
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-react'
|
||||
import { Navbar } from '@/components/landing/Navbar'
|
||||
import { Hero } from '@/components/landing/Hero'
|
||||
import { Features } from '@/components/landing/Features'
|
||||
import { HowItWorks } from '@/components/landing/HowItWorks'
|
||||
import { Testimonials } from '@/components/landing/Testimonials'
|
||||
import { TrustSection } from '@/components/landing/TrustSection'
|
||||
import { Pricing } from '@/components/landing/Pricing'
|
||||
import { FAQ } from '@/components/landing/FAQ'
|
||||
import { Footer } from '@/components/landing/Footer'
|
||||
import { HorizontalScrollNav } from '@/components/landing/HorizontalScrollNav'
|
||||
|
||||
const sections = [
|
||||
{ id: 'features', name: 'Features' },
|
||||
{ id: 'how-it-works', name: 'How It Works' },
|
||||
{ id: 'pricing', name: 'Pricing' },
|
||||
{ id: 'faq', name: 'FAQ' }
|
||||
]
|
||||
|
||||
export function Home() {
|
||||
const scrollContainerRef = useRef<HTMLDivElement>(null)
|
||||
const [activeIndex, setActiveIndex] = useState(0)
|
||||
|
||||
// Scroll to specific section
|
||||
const scrollToSection = useCallback((index: number) => {
|
||||
const container = scrollContainerRef.current
|
||||
if (!container) return
|
||||
|
||||
const sectionWidth = container.clientWidth
|
||||
container.scrollTo({
|
||||
left: index * sectionWidth,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
}, [])
|
||||
|
||||
// Track active section based on scroll position
|
||||
useEffect(() => {
|
||||
const container = scrollContainerRef.current
|
||||
if (!container) return
|
||||
|
||||
const handleScroll = () => {
|
||||
const scrollLeft = container.scrollLeft
|
||||
const sectionWidth = container.clientWidth
|
||||
const index = Math.round(scrollLeft / sectionWidth)
|
||||
setActiveIndex(index)
|
||||
}
|
||||
|
||||
container.addEventListener('scroll', handleScroll, { passive: true })
|
||||
return () => container.removeEventListener('scroll', handleScroll)
|
||||
}, [])
|
||||
|
||||
// Keyboard navigation
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
// Only handle arrow keys when horizontal scroll container is in view
|
||||
const container = scrollContainerRef.current
|
||||
if (!container) return
|
||||
|
||||
const rect = container.getBoundingClientRect()
|
||||
const isVisible = rect.top < window.innerHeight && rect.bottom > 0
|
||||
|
||||
if (!isVisible) return
|
||||
|
||||
if (e.key === 'ArrowRight' && activeIndex < 3) {
|
||||
e.preventDefault()
|
||||
scrollToSection(activeIndex + 1)
|
||||
} else if (e.key === 'ArrowLeft' && activeIndex > 0) {
|
||||
e.preventDefault()
|
||||
scrollToSection(activeIndex - 1)
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown)
|
||||
return () => window.removeEventListener('keydown', handleKeyDown)
|
||||
}, [activeIndex, scrollToSection])
|
||||
|
||||
// Listen for custom events from Navbar
|
||||
useEffect(() => {
|
||||
const handleHorizontalScroll = (e: Event) => {
|
||||
const customEvent = e as CustomEvent<{ sectionId: string }>
|
||||
const sectionId = customEvent.detail.sectionId
|
||||
const sectionIndex = sections.findIndex(s => s.id === sectionId)
|
||||
if (sectionIndex !== -1) {
|
||||
// Small delay to ensure container is ready
|
||||
setTimeout(() => {
|
||||
scrollToSection(sectionIndex)
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('scrollToHorizontalSection', handleHorizontalScroll as EventListener)
|
||||
return () => {
|
||||
window.removeEventListener('scrollToHorizontalSection', handleHorizontalScroll as EventListener)
|
||||
}
|
||||
}, [scrollToSection])
|
||||
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
{/* NAVBAR - fixed top */}
|
||||
<Navbar />
|
||||
|
||||
{/* HERO SECTION - normal vertical scroll */}
|
||||
<section className="hero-section min-h-screen">
|
||||
<Hero />
|
||||
</section>
|
||||
|
||||
{/* HORIZONTAL SCROLL CONTAINER */}
|
||||
<div className="relative group">
|
||||
{/* Horizontal Scroll Area */}
|
||||
<div
|
||||
ref={scrollContainerRef}
|
||||
className="flex overflow-x-auto overflow-y-hidden snap-x snap-mandatory scroll-smooth scrollbar-hide"
|
||||
style={{
|
||||
scrollbarWidth: 'none',
|
||||
msOverflowStyle: 'none',
|
||||
WebkitOverflowScrolling: 'touch'
|
||||
}}
|
||||
>
|
||||
{/* Section 1: Features */}
|
||||
<div className="w-screen min-h-screen snap-center flex-shrink-0 flex items-center justify-center">
|
||||
<div className="w-full">
|
||||
<Features />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Section 2: How It Works */}
|
||||
<div className="w-screen min-h-screen snap-center flex-shrink-0 flex items-center justify-center">
|
||||
<div className="w-full">
|
||||
<HowItWorks />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Section 3: Pricing */}
|
||||
<div className="w-screen min-h-screen snap-center flex-shrink-0 flex items-center justify-center">
|
||||
<div className="w-full">
|
||||
<Pricing />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Section 4: FAQ */}
|
||||
<div className="w-screen min-h-screen snap-center flex-shrink-0 flex items-center justify-center">
|
||||
<div className="w-full">
|
||||
<FAQ />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Left Arrow - appears on hover */}
|
||||
<button
|
||||
onClick={() => scrollToSection(Math.max(0, activeIndex - 1))}
|
||||
className="fixed left-8 top-1/2 -translate-y-1/2 z-50 opacity-0 group-hover:opacity-100 transition-opacity duration-300 bg-slate-900/90 dark:bg-slate-800/90 hover:bg-slate-800 dark:hover:bg-slate-700 p-4 rounded-lg shadow-xl backdrop-blur-sm"
|
||||
disabled={activeIndex === 0}
|
||||
aria-label="Previous section"
|
||||
>
|
||||
<ChevronLeft className="w-6 h-6 text-white" />
|
||||
</button>
|
||||
|
||||
{/* Right Arrow - appears on hover */}
|
||||
<button
|
||||
onClick={() => scrollToSection(Math.min(3, activeIndex + 1))}
|
||||
className="fixed right-8 top-1/2 -translate-y-1/2 z-50 opacity-0 group-hover:opacity-100 transition-opacity duration-300 bg-slate-900/90 dark:bg-slate-800/90 hover:bg-slate-800 dark:hover:bg-slate-700 p-4 rounded-lg shadow-xl backdrop-blur-sm"
|
||||
disabled={activeIndex === 3}
|
||||
aria-label="Next section"
|
||||
>
|
||||
<ChevronRight className="w-6 h-6 text-white" />
|
||||
</button>
|
||||
|
||||
{/* Scroll Indicators (Dots) */}
|
||||
<HorizontalScrollNav
|
||||
sections={sections}
|
||||
activeIndex={activeIndex}
|
||||
onNavigate={scrollToSection}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* TESTIMONIALS - normal vertical scroll */}
|
||||
<section className="testimonials-section py-20">
|
||||
<Testimonials />
|
||||
</section>
|
||||
|
||||
{/* FOOTER - normal vertical scroll */}
|
||||
<footer className="footer-section">
|
||||
<TrustSection />
|
||||
<Pricing />
|
||||
<FAQ />
|
||||
<Footer />
|
||||
</footer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user