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) => {
|
const scrollToSection = useCallback((sectionId: string) => {
|
||||||
setIsMenuOpen(false)
|
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 not on home page, navigate first
|
||||||
if (location.pathname !== '/') {
|
if (location.pathname !== '/') {
|
||||||
navigate('/')
|
navigate('/')
|
||||||
|
|||||||
@@ -84,7 +84,6 @@
|
|||||||
/* Base styles */
|
/* Base styles */
|
||||||
html {
|
html {
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
overflow-x: hidden; /* Prevent horizontal scroll on body */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@@ -94,8 +93,6 @@ body {
|
|||||||
/* Improve touch scrolling on mobile */
|
/* Improve touch scrolling on mobile */
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
overflow-scrolling: touch;
|
overflow-scrolling: touch;
|
||||||
/* Prevent horizontal scroll */
|
|
||||||
overflow-x: hidden;
|
|
||||||
/* Base colors - Tailwind will handle dark mode */
|
/* Base colors - Tailwind will handle dark mode */
|
||||||
background-color: var(--color-slate-50);
|
background-color: var(--color-slate-50);
|
||||||
color: var(--color-slate-900);
|
color: var(--color-slate-900);
|
||||||
@@ -327,38 +324,3 @@ body {
|
|||||||
html:not(.dark-mode-initialized) body {
|
html:not(.dark-mode-initialized) body {
|
||||||
transition: none;
|
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 { Navbar } from '@/components/landing/Navbar'
|
||||||
import { Hero } from '@/components/landing/Hero'
|
import { Hero } from '@/components/landing/Hero'
|
||||||
import { Features } from '@/components/landing/Features'
|
import { Features } from '@/components/landing/Features'
|
||||||
import { HowItWorks } from '@/components/landing/HowItWorks'
|
import { HowItWorks } from '@/components/landing/HowItWorks'
|
||||||
import { Testimonials } from '@/components/landing/Testimonials'
|
import { Testimonials } from '@/components/landing/Testimonials'
|
||||||
|
import { TrustSection } from '@/components/landing/TrustSection'
|
||||||
import { Pricing } from '@/components/landing/Pricing'
|
import { Pricing } from '@/components/landing/Pricing'
|
||||||
import { FAQ } from '@/components/landing/FAQ'
|
import { FAQ } from '@/components/landing/FAQ'
|
||||||
import { Footer } from '@/components/landing/Footer'
|
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() {
|
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 (
|
return (
|
||||||
<div className="min-h-screen">
|
<div className="min-h-screen">
|
||||||
{/* NAVBAR - fixed top */}
|
|
||||||
<Navbar />
|
<Navbar />
|
||||||
|
|
||||||
{/* HERO SECTION - normal vertical scroll */}
|
|
||||||
<section className="hero-section min-h-screen">
|
|
||||||
<Hero />
|
<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 />
|
<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 />
|
<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 />
|
<Testimonials />
|
||||||
</section>
|
<TrustSection />
|
||||||
|
<Pricing />
|
||||||
{/* FOOTER - normal vertical scroll */}
|
<FAQ />
|
||||||
<footer className="footer-section">
|
|
||||||
<Footer />
|
<Footer />
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user