b
This commit is contained in:
35
components/Footer.tsx
Normal file
35
components/Footer.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import Link from 'next/link'
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="w-full bg-[#111111] text-white pt-12 pb-16 px-6 md:px-10 border-t border-white/10">
|
||||
<div className="flex flex-col space-y-12 md:space-y-0 md:flex-row md:justify-between md:items-end">
|
||||
|
||||
{/* Left Side Branding */}
|
||||
<div className="text-[32px] md:text-[20px] font-bebas tracking-tighter leading-none text-center md:text-left">
|
||||
A.N.T
|
||||
</div>
|
||||
|
||||
{/* Center: Copyright & Credits */}
|
||||
<div className="flex flex-col items-center space-y-4 md:space-y-0 md:pb-1">
|
||||
<div className="text-[9px] md:text-[10px] font-extrabold uppercase tracking-[0.15em] text-white/40 text-center leading-relaxed max-w-[300px] md:max-w-none">
|
||||
©A.N.T ARCHITECTURE INC. 2026
|
||||
</div>
|
||||
<div className="text-[9px] md:text-[10px] font-extrabold uppercase tracking-[0.15em] text-white/40 text-center flex flex-wrap justify-center gap-x-2">
|
||||
<span className="hidden md:inline">CREATED BY
|
||||
</span>
|
||||
<Link href="https://ayris.tech" className="hover:text-white transition-colors underline md:no-underline">AYRISTECH</Link>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Side Branding */}
|
||||
<div className="text-[32px] md:text-[20px] font-bebas tracking-tighter leading-none text-center md:text-right">
|
||||
ARCHITECTURE
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
20
components/LayoutContent.tsx
Normal file
20
components/LayoutContent.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
'use client'
|
||||
|
||||
import { usePathname } from "next/navigation";
|
||||
import Navbar from "@/components/Navbar";
|
||||
import Footer from "@/components/Footer";
|
||||
|
||||
export default function LayoutContent({ children }: { children: React.ReactNode }) {
|
||||
const pathname = usePathname();
|
||||
const isHome = pathname === "/";
|
||||
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
<div className="flex-1">
|
||||
{children}
|
||||
</div>
|
||||
{!isHome && <Footer />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
150
components/Navbar.tsx
Normal file
150
components/Navbar.tsx
Normal file
@@ -0,0 +1,150 @@
|
||||
'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>
|
||||
</>
|
||||
)
|
||||
}
|
||||
76
components/ProjectSlider.tsx
Normal file
76
components/ProjectSlider.tsx
Normal file
@@ -0,0 +1,76 @@
|
||||
'use client'
|
||||
|
||||
import { useRef, useEffect } from 'react'
|
||||
import { motion, useAnimationFrame } from 'framer-motion'
|
||||
import Image from 'next/image'
|
||||
import { Project } from '@/data/projects'
|
||||
|
||||
interface ProjectSliderProps {
|
||||
projects: Project[]
|
||||
}
|
||||
|
||||
export default function ProjectSlider({ projects }: ProjectSliderProps) {
|
||||
const containerRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
// Duplicate projects for seamless infinite loop
|
||||
const doubledProjects = [...projects, ...projects]
|
||||
|
||||
// Speed of the automatic scroll
|
||||
const speed = 0.8
|
||||
|
||||
useAnimationFrame(() => {
|
||||
if (!containerRef.current) return
|
||||
|
||||
containerRef.current.scrollLeft += speed
|
||||
|
||||
const firstHalfWidth = containerRef.current.scrollWidth / 2
|
||||
|
||||
if (containerRef.current.scrollLeft >= firstHalfWidth) {
|
||||
containerRef.current.scrollLeft = 0
|
||||
}
|
||||
})
|
||||
|
||||
const handleWheel = (e: React.WheelEvent) => {
|
||||
if (!containerRef.current) return
|
||||
containerRef.current.scrollLeft += e.deltaY
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
onWheel={handleWheel}
|
||||
className="flex-1 flex items-center overflow-x-auto no-scrollbar cursor-grab active:cursor-grabbing py-10"
|
||||
>
|
||||
<div className="flex space-x-6 md:space-x-12 px-6 md:px-10">
|
||||
{doubledProjects.map((project, idx) => (
|
||||
<div
|
||||
key={`${project.id}-${idx}`}
|
||||
className="group relative flex-shrink-0 w-[80vw] sm:w-[500px] md:w-[600px]"
|
||||
>
|
||||
{/* Image Container */}
|
||||
<div className="relative aspect-[4/3] overflow-hidden rounded-[1px]">
|
||||
<Image
|
||||
src={project.image}
|
||||
alt={project.title}
|
||||
fill
|
||||
sizes="(max-width: 768px) 80vw, 600px"
|
||||
className="object-cover grayscale hover:grayscale-0 transition-all duration-700 ease-in-out scale-110 group-hover:scale-100"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Project Info */}
|
||||
<div className="mt-4 flex justify-between items-start opacity-0 group-hover:opacity-100 transition-opacity duration-500">
|
||||
<div className="text-[10px] md:text-[12px] font-bold text-black tracking-wider uppercase">
|
||||
{project.year} — {project.location}
|
||||
</div>
|
||||
<div className="flex items-center space-x-2 text-[10px] md:text-[12px] font-bold text-black tracking-wider uppercase">
|
||||
<span>{project.title}</span>
|
||||
<span className="text-sm md:text-lg">→</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user