Initial commit
This commit is contained in:
111
src/App.tsx
Normal file
111
src/App.tsx
Normal file
@@ -0,0 +1,111 @@
|
||||
import { useState, useEffect, useRef, useCallback } from 'react'
|
||||
import Lenis from 'lenis'
|
||||
import { gsap } from 'gsap'
|
||||
import { ScrollTrigger } from 'gsap/ScrollTrigger'
|
||||
|
||||
import LoadingScreen from './components/LoadingScreen'
|
||||
import Navigation from './components/Navigation'
|
||||
import HeroSection from './components/HeroSection'
|
||||
import AboutSection from './components/AboutSection'
|
||||
import InterestsSection from './components/InterestsSection'
|
||||
import ProjectsSection from './components/ProjectsSection'
|
||||
import ExperienceSection from './components/ExperienceSection'
|
||||
import TopicsSection from './components/TopicsSection'
|
||||
import ContactSection from './components/ContactSection'
|
||||
import Footer from './components/Footer'
|
||||
import FloatingParticles from './components/FloatingParticles'
|
||||
import ScrollProgress from './components/ScrollProgress'
|
||||
import NoiseOverlay from './components/NoiseOverlay'
|
||||
import { useReducedMotion } from './hooks/useReducedMotion'
|
||||
|
||||
gsap.registerPlugin(ScrollTrigger)
|
||||
|
||||
export default function App() {
|
||||
const [loaded, setLoaded] = useState(false)
|
||||
const [showContent, setShowContent] = useState(false)
|
||||
const lenisRef = useRef<Lenis | null>(null)
|
||||
const mainRef = useRef<HTMLElement>(null)
|
||||
const capiAudioRef = useRef<HTMLAudioElement | null>(null)
|
||||
const reducedMotion = useReducedMotion()
|
||||
|
||||
useEffect(() => {
|
||||
capiAudioRef.current = new Audio('./media/capi.mp3')
|
||||
capiAudioRef.current.preload = 'auto'
|
||||
capiAudioRef.current.loop = true
|
||||
capiAudioRef.current.volume = 0.25
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!loaded) return
|
||||
|
||||
const lenis = new Lenis({
|
||||
duration: 1.2,
|
||||
easing: (t: number) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
|
||||
smoothWheel: true,
|
||||
})
|
||||
lenisRef.current = lenis
|
||||
|
||||
lenis.on('scroll', ScrollTrigger.update)
|
||||
|
||||
const rafCallback = (time: number) => {
|
||||
lenis.raf(time * 1000)
|
||||
}
|
||||
gsap.ticker.add(rafCallback)
|
||||
gsap.ticker.lagSmoothing(0)
|
||||
|
||||
return () => {
|
||||
gsap.ticker.remove(rafCallback)
|
||||
lenis.destroy()
|
||||
}
|
||||
}, [loaded])
|
||||
|
||||
const handleLoadComplete = useCallback(() => {
|
||||
setLoaded(true)
|
||||
// Small delay before showing content for transition
|
||||
setTimeout(() => {
|
||||
setShowContent(true)
|
||||
}, 100)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (showContent) {
|
||||
// Start ambient capi.mp3 loop
|
||||
capiAudioRef.current?.play().catch(() => {})
|
||||
}
|
||||
}, [showContent])
|
||||
|
||||
useEffect(() => {
|
||||
if (showContent && mainRef.current && !reducedMotion) {
|
||||
gsap.fromTo(
|
||||
mainRef.current,
|
||||
{ opacity: 0, y: 40 },
|
||||
{ opacity: 1, y: 0, duration: 1.2, ease: 'expo.out' }
|
||||
)
|
||||
}
|
||||
}, [showContent, reducedMotion])
|
||||
|
||||
return (
|
||||
<>
|
||||
<LoadingScreen onLoadComplete={handleLoadComplete} />
|
||||
|
||||
{showContent && (
|
||||
<>
|
||||
<ScrollProgress />
|
||||
<NoiseOverlay />
|
||||
<FloatingParticles />
|
||||
<Navigation />
|
||||
<main ref={mainRef} className="relative" style={{ opacity: reducedMotion ? 1 : 0 }}>
|
||||
<HeroSection />
|
||||
<AboutSection />
|
||||
<InterestsSection />
|
||||
<ProjectsSection />
|
||||
<ExperienceSection />
|
||||
<TopicsSection />
|
||||
<ContactSection />
|
||||
<Footer />
|
||||
</main>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user