Portfolio / frontend /src /App.jsx
parthib07's picture
Upload 32 files
0ed2558 verified
import { useState, useEffect } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import Navbar from './components/Navbar'
import Hero from './components/Hero'
import About from './components/About'
import Skills from './components/Skills'
import Experience from './components/Experience'
import Publications from './components/Publications'
import Projects from './components/Projects'
import Education from './components/Education'
import Achievements from './components/Achievements'
import Blog from './components/Blog'
import Contact from './components/Contact'
import Footer from './components/Footer'
import Terminal from './components/Terminal'
function Loader({ done }) {
return (
<AnimatePresence>
{!done && (
<motion.div
key="loader"
initial={{ opacity: 1 }}
exit={{ opacity: 0, transition: { duration: 0.5 } }}
style={{
position: 'fixed', inset: 0, zIndex: 9999,
background: 'var(--bg-primary)',
display: 'flex', flexDirection: 'column',
alignItems: 'center', justifyContent: 'center', gap: 20,
}}
>
<motion.div
style={{
fontFamily: 'var(--font-display)', fontSize: '2rem', fontWeight: 800,
background: 'linear-gradient(135deg, #6366f1, #06b6d4)',
WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent', backgroundClip: 'text',
}}
animate={{ opacity: [0.4, 1, 0.4] }}
transition={{ duration: 1.4, repeat: Infinity }}
>
Parthib Karak.
</motion.div>
<div style={{ width: 160, height: 2, background: 'rgba(99,102,241,0.12)', borderRadius: 99, overflow: 'hidden' }}>
<motion.div
style={{ height: '100%', background: 'linear-gradient(90deg, #6366f1, #06b6d4)', borderRadius: 99 }}
initial={{ width: '0%' }}
animate={{ width: '100%' }}
transition={{ duration: 1.1, ease: 'easeInOut' }}
/>
</div>
</motion.div>
)}
</AnimatePresence>
)
}
function ScrollTopBtn() {
const [visible, setVisible] = useState(false)
useEffect(() => {
const fn = () => setVisible(window.scrollY > 600)
window.addEventListener('scroll', fn, { passive: true })
return () => window.removeEventListener('scroll', fn)
}, [])
if (!visible) return null
return (
<motion.button
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
style={{
position: 'fixed', bottom: 92, right: 28, zIndex: 50,
width: 44, height: 44, borderRadius: '50%',
background: 'linear-gradient(135deg, var(--accent-primary), var(--accent-secondary))',
border: 'none', cursor: 'pointer', color: 'white',
display: 'flex', alignItems: 'center', justifyContent: 'center',
fontSize: '1.1rem', boxShadow: '0 6px 20px rgba(99,102,241,0.4)',
}}
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0 }}
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.95 }}
aria-label="Scroll to top"
>
</motion.button>
)
}
export default function App() {
const [theme, setTheme] = useState('dark')
const [loaded, setLoaded] = useState(false)
useEffect(() => {
document.documentElement.setAttribute('data-theme', theme)
}, [theme])
useEffect(() => {
const t = setTimeout(() => setLoaded(true), 1300)
return () => clearTimeout(t)
}, [])
return (
<>
<Loader done={loaded} />
<div className="noise-overlay" aria-hidden="true" />
<Navbar theme={theme} setTheme={setTheme} />
<main>
<Hero />
<About />
<Skills />
<Experience />
<Publications />
<Projects />
<Education />
<Achievements />
<Blog />
<Contact />
</main>
<Footer />
<Terminal />
<ScrollTopBtn />
</>
)
}