151 lines
5.7 KiB
TypeScript
151 lines
5.7 KiB
TypeScript
'use client'
|
||
|
||
import { useState, useEffect } from 'react'
|
||
import Link from 'next/link'
|
||
import { motion, AnimatePresence } from 'framer-motion'
|
||
|
||
const navLinks = [
|
||
{ name: 'ANASAYFA', href: '/' },
|
||
{ name: 'PROJELER', href: '/projects' },
|
||
{ name: 'HAKKIMIZDA', href: '/about' },
|
||
{ name: 'İLETİŞİM', href: '/contact' },
|
||
]
|
||
|
||
// Slot machine style link – text rolls down from top on hover
|
||
function SlotLink({ href, children, className = '' }: { href: string, children: string, className?: string }) {
|
||
return (
|
||
<Link href={href} className={`relative inline-block overflow-hidden group ${className}`}>
|
||
<span className="block transition-transform duration-300 ease-[cubic-bezier(0.76,0,0.24,1)] group-hover:translate-y-full">
|
||
{children}
|
||
</span>
|
||
<span className="absolute left-0 top-0 block -translate-y-full transition-transform duration-300 ease-[cubic-bezier(0.76,0,0.24,1)] group-hover:translate-y-0" aria-hidden="true">
|
||
{children}
|
||
</span>
|
||
</Link>
|
||
)
|
||
}
|
||
|
||
export default function Navbar() {
|
||
const [isScrolled, setIsScrolled] = useState(false)
|
||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
|
||
|
||
useEffect(() => {
|
||
const handleScroll = () => {
|
||
setIsScrolled(window.scrollY > 80)
|
||
}
|
||
window.addEventListener('scroll', handleScroll)
|
||
return () => window.removeEventListener('scroll', handleScroll)
|
||
}, [])
|
||
|
||
return (
|
||
<>
|
||
{/* INITIAL NAVBAR */}
|
||
<motion.nav
|
||
initial={{ y: 0, opacity: 1 }}
|
||
animate={{
|
||
y: isScrolled ? -100 : 0,
|
||
opacity: isScrolled ? 0 : 1
|
||
}}
|
||
transition={{ duration: 0.5, ease: [0.33, 1, 0.68, 1] }}
|
||
className="fixed top-0 left-0 w-full flex items-center justify-center px-6 md:px-10 py-6 z-[100] bg-white/80 backdrop-blur-md uppercase text-[12px] font-extrabold tracking-[0.05em] text-black"
|
||
>
|
||
{/* Mobile: Logo left + hamburger right */}
|
||
<div className="flex-1 md:hidden">
|
||
<Link href="/" className="text-[16px] font-bebas tracking-tighter">A.N.T</Link>
|
||
</div>
|
||
|
||
{/* Desktop Links – centered */}
|
||
<div className="hidden md:flex items-center space-x-8">
|
||
{navLinks.map((link) => (
|
||
<SlotLink key={link.name} href={link.href}>
|
||
{link.name}
|
||
</SlotLink>
|
||
))}
|
||
</div>
|
||
|
||
{/* Mobile Menu Toggle */}
|
||
<div className="md:hidden">
|
||
<button
|
||
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
|
||
className="flex flex-col space-y-1.5 p-2"
|
||
>
|
||
<span className={`block w-6 h-0.5 bg-black transition-transform ${isMobileMenuOpen ? 'rotate-45 translate-y-2' : ''}`} />
|
||
<span className={`block w-6 h-0.5 bg-black transition-opacity ${isMobileMenuOpen ? 'opacity-0' : ''}`} />
|
||
<span className={`block w-6 h-0.5 bg-black transition-transform ${isMobileMenuOpen ? '-rotate-45 -translate-y-2' : ''}`} />
|
||
</button>
|
||
</div>
|
||
</motion.nav>
|
||
|
||
{/* SCROLLED COMPACT NAVBAR */}
|
||
<AnimatePresence>
|
||
{isScrolled && !isMobileMenuOpen && (
|
||
<motion.div
|
||
initial={{ y: -50, opacity: 0, x: 20 }}
|
||
animate={{ y: 24, opacity: 1, x: -24 }}
|
||
exit={{ y: -50, opacity: 0, x: 20 }}
|
||
transition={{ duration: 0.5, ease: [0.33, 1, 0.68, 1] }}
|
||
className="fixed top-0 right-0 z-[100] flex items-stretch h-12 bg-black text-white rounded-[2px] overflow-hidden shadow-2xl"
|
||
>
|
||
<div className="hidden md:flex items-center px-6 space-x-6">
|
||
{navLinks.map((link) => (
|
||
<SlotLink
|
||
key={link.name}
|
||
href={link.href}
|
||
className="text-[10px] font-extrabold tracking-widest uppercase"
|
||
>
|
||
{link.name}
|
||
</SlotLink>
|
||
))}
|
||
</div>
|
||
|
||
{/* Scrolled Mobile Toggle */}
|
||
<button
|
||
onClick={() => setIsMobileMenuOpen(true)}
|
||
className="md:hidden px-4 flex items-center"
|
||
>
|
||
<span className="text-[10px] font-extrabold tracking-widest">MENÜ</span>
|
||
</button>
|
||
</motion.div>
|
||
)}
|
||
</AnimatePresence>
|
||
|
||
{/* MOBILE OVERLAY MENU */}
|
||
<AnimatePresence>
|
||
{isMobileMenuOpen && (
|
||
<motion.div
|
||
initial={{ opacity: 0 }}
|
||
animate={{ opacity: 1 }}
|
||
exit={{ opacity: 0 }}
|
||
className="fixed inset-0 z-[150] bg-white flex flex-col p-10"
|
||
>
|
||
<div className="flex justify-between items-center mb-20">
|
||
<Link href="/" onClick={() => setIsMobileMenuOpen(false)} className="text-[24px] font-bebas tracking-tighter">A.N.T</Link>
|
||
<button onClick={() => setIsMobileMenuOpen(false)} className="text-[12px] font-extrabold tracking-widest">KAPAT</button>
|
||
</div>
|
||
|
||
<div className="flex flex-col space-y-8">
|
||
{navLinks.map((link) => (
|
||
<Link
|
||
key={link.name}
|
||
href={link.href}
|
||
onClick={() => setIsMobileMenuOpen(false)}
|
||
className="text-[40px] font-bebas tracking-tight text-black hover:pl-4 transition-all duration-300"
|
||
>
|
||
{link.name}
|
||
</Link>
|
||
))}
|
||
</div>
|
||
|
||
<div className="mt-auto pt-10 border-t border-black/5">
|
||
<div className="flex items-center space-x-6 text-[12px] font-bold text-black">
|
||
<button className="underline underline-offset-4">TR</button>
|
||
<button className="opacity-40">EN</button>
|
||
</div>
|
||
</div>
|
||
</motion.div>
|
||
)}
|
||
</AnimatePresence>
|
||
</>
|
||
)
|
||
}
|