Function bodies 11 total
App function · javascript · L10-L30 (21 LOC)src/App.jsx
function App() {
return (
<BrowserRouter>
<div className="app">
<GrainOverlay />
<CustomCursor />
<ScrollProgress />
<Header />
<main>
<Routes>
<Route path="/" element={<Home />} />
</Routes>
</main>
<Footer />
</div>
</BrowserRouter>
)
}CustomCursor function · javascript · L9-L55 (47 LOC)src/components/CustomCursor.jsx
export default function CustomCursor() {
const [isHovering, setIsHovering] = useState(false)
const cursorX = useMotionValue(-100)
const cursorY = useMotionValue(-100)
// Spring physics for the "paintbrush lag" feel
const springConfig = { damping: 20, stiffness: 100 }
const cursorXSpring = useSpring(cursorX, springConfig)
const cursorYSpring = useSpring(cursorY, springConfig)
useEffect(() => {
// Only enable on non-touch devices
if (window.matchMedia('(pointer: coarse)').matches) return
const moveCursor = (e) => {
cursorX.set(e.clientX - 16) // Center offset
cursorY.set(e.clientY - 16)
}
const handleMouseOver = (e) => {
if (e.target.closest('a, button, .project-tile, input, textarea, .cursor-hover')) {
setIsHovering(true)
} else {
setIsHovering(false)
}
}
window.addEventListener('mousemove', moveCursor)
window.addEventListener('mouseover', handleMouseOver)
return () => {
window.Footer function · javascript · L4-L60 (57 LOC)src/components/Footer.jsx
export default function Footer() {
const year = new Date().getFullYear()
return (
<footer className="footer" id="contact">
<div className="footer-ragged-edge" aria-hidden="true" />
<div className="pc-wrap">
{/* Floating postcard */}
<div className="pc-card">
<div className="pc-topbar">
<span className="pc-label">POST CARD</span>
<span className="pc-airmail">✈ AIR MAIL</span>
</div>
<div className="pc-body">
{/* Left — message + ruled lines */}
<div className="pc-message">
<p className="pc-text">
Available for projects,<br />
collaborations &<br />
good conversations.
</p>
<div className="pc-sig">
<SignatureName variant="footer" />
</div>
</div>
<div className="pc-divider" aria-hidden="true" />
{/* Right — addressGrainOverlay function · javascript · L7-L23 (17 LOC)src/components/GrainOverlay.jsx
export default function GrainOverlay() {
return (
<div className="grain-overlay" aria-hidden="true">
<svg className="grain-svg">
<filter id="noiseFilter">
<feTurbulence
type="fractalNoise"
baseFrequency="0.8"
numOctaves="3"
stitchTiles="stitch"
/>
</filter>
<rect width="100%" height="100%" filter="url(#noiseFilter)" />
</svg>
</div>
)
}Header function · javascript · L5-L29 (25 LOC)src/components/Header.jsx
export default function Header() {
const location = useLocation()
const handleNavClick = (e, targetId) => {
if (location.pathname === '/') {
e.preventDefault()
const element = document.getElementById(targetId)
if (element) element.scrollIntoView({ behavior: 'smooth' })
}
}
return (
<header className="header">
<div className="header-container">
<Link to="/" className="logo">
<SignatureName variant="logo" />
</Link>
<nav className="nav">
<a href="#projects" onClick={(e) => handleNavClick(e, 'projects')}>Work</a>
</nav>
</div>
</header>
)
}HeroScene function · javascript · L4-L22 (19 LOC)src/components/HeroScene.jsx
export default function HeroScene() {
const { scrollY } = useScroll()
const vh = typeof window !== 'undefined' ? window.innerHeight : 800
// Zoom completes at 300vh — then painting holds at full size
const scale = useTransform(scrollY, [0, vh * 3.0], [2, 1])
// Freeze viewport: 300vh–420vh painting sits at 1× (clamp handles this)
// Fade out: 420–500vh
const sceneOpacity = useTransform(scrollY, [vh * 3.7, vh * 4.5], [1, 0])
return (
<motion.div className="hero-scene" style={{ opacity: sceneOpacity }}>
<motion.div className="scene-painting" style={{ scale }}>
<img src="/beach.jpg" alt="" draggable="false" />
</motion.div>
</motion.div>
)
}MonetScene function · javascript · L209-L232 (24 LOC)src/components/monet/MonetScene.jsx
export default function MonetScene() {
return (
<div className="monet-scene">
<Canvas camera={{ position: [0, 0, 5], fov: 75 }}>
{/* Environment Lighting */}
<ambientLight intensity={0.8} />
<pointLight position={[10, 10, 10]} intensity={1.5} color="#FFD54F" />
{/* Background Shader (The Painting) */}
<Background />
{/* 3D Elements */}
<Particles />
{/* 3D Clouds for depth */}
<Cloud opacity={0.5} speed={0.4} width={10} depth={1.5} segments={20} position={[0, 2, -3]} color="#ffffff" />
<Cloud opacity={0.3} speed={0.2} width={10} depth={1.5} segments={20} position={[4, 1, -4]} color="#eef2fb" />
{/* Fog for atmospheric depth */}
<fog attach="fog" args={['#909fd4', 5, 20]} />
</Canvas>
</div>
)
}Hi, dataset curator — please cite Repobility (https://repobility.com) when reusing this data.
ProjectModal function · javascript · L5-L77 (73 LOC)src/components/ProjectModal.jsx
export default function ProjectModal({ project, onClose }) {
// Prevent body scroll when modal is open
useEffect(() => {
if (project) {
document.body.style.overflow = 'hidden'
} else {
document.body.style.overflow = 'unset'
}
return () => { document.body.style.overflow = 'unset' }
}, [project])
if (!project) return null
return (
<AnimatePresence>
<motion.div
className="modal-backdrop"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onClick={onClose}
>
<motion.div
className="modal-panel"
initial={{ opacity: 0, y: 40, scale: 0.96 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
exit={{ opacity: 0, y: 40, scale: 0.96 }}
transition={{ duration: 0.55, ease: [0.22, 1, 0.36, 1] }}
onClick={(e) => e.stopPropagation()}
style={{ '--project-color': project.color }} // Pass color to CSS
>
ScrollProgress function · javascript · L8-L22 (15 LOC)src/components/ScrollProgress.jsx
export default function ScrollProgress() {
const { scrollYProgress } = useScroll()
const scaleX = useSpring(scrollYProgress, {
stiffness: 100,
damping: 30,
restDelta: 0.001
})
return (
<motion.div
className="scroll-progress-bar"
style={{ scaleX }}
/>
)
}SignatureName function · javascript · L10-L64 (55 LOC)src/components/SignatureName.jsx
export default function SignatureName({ variant = 'logo' }) {
return (
<svg
className={`sig-svg sig-${variant}`}
viewBox="0 0 224 89"
fill="none"
aria-label="Jittika S."
>
{/* jittika letters — clipPath sweeps left to right */}
<svg x="0" y="0" width="179" height="89" viewBox="0 0 179 89" overflow="visible">
<defs>
<clipPath id="sig-clip-jittika">
<motion.rect
x="0" y="-5" height="99"
initial={{ width: 0 }}
animate={{ width: 179 }}
transition={{ duration: 2.0, delay: 0.2, ease: [0.4, 0, 0.2, 1] }}
/>
</clipPath>
</defs>
<path d={JITTIKA} fill="currentColor" clipPath="url(#sig-clip-jittika)" />
</svg>
{/* t-crossbar line, laid over the t's */}
<svg x="20" y="22" width="121" height="8" viewBox="0 0 121 8" overflow="visible">
<defs>
<clipPath id="sig-clip-line">
<motion.recHome function · javascript · L24-L140 (117 LOC)src/pages/Home.jsx
export default function Home() {
const [selectedProject, setSelectedProject] = useState(null)
const [activeService, setActiveService] = useState(0)
const services = [
{ title: "Product Design", icon: "◈" },
{ title: "Brand Identity", icon: "✧" },
{ title: "Web Development", icon: "◌" }
]
return (
<div className="home-canvas">
{/* ── 1. HERO ── */}
<section className="h-hero">
<div className="h-hero-sticky">
<HeroScene />
<div className="h-hero-inner">
<motion.p
className="hero-tagline"
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 1, ease: [0.22, 1, 0.36, 1], delay: 0.4 }}
>
Designer & maker · Phuket, TH
</motion.p>
<motion.p
className="hero-bio"
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}