underrate's picture
Initial commit
34ed5b1 verified
Raw
History Blame Contribute Delete
10.4 kB
"use client"
import Link from "next/link"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Github, Linkedin, Mail, ArrowRight, Sparkles, Heart } from "lucide-react"
import { useRef, useState, useEffect } from "react"
const footerLinks = [
{
title: "Services",
links: [
{ name: "Web Development", href: "/services" },
{ name: "App Development", href: "/services" },
{ name: "UI/UX Design", href: "/services" },
{ name: "SEO Optimization", href: "/services" },
],
},
{
title: "Company",
links: [
{ name: "About Us", href: "/about" },
{ name: "Portfolio", href: "/portfolio" },
{ name: "Blog", href: "/blog" },
{ name: "Contact", href: "/contact" },
],
},
{
title: "Legal",
links: [
{ name: "Privacy Policy", href: "/privacy" },
{ name: "Terms of Service", href: "/terms" },
{ name: "Cookie Policy", href: "/cookies" },
],
},
]
const socialLinks = [
{ icon: Github, href: "#", label: "GitHub", color: "hover:text-white" },
{ icon: Linkedin, href: "#", label: "LinkedIn", color: "hover:text-blue-400" },
{ icon: Mail, href: "mailto:hello@nexaflow.dev", label: "Email", color: "hover:text-primary" },
]
export function Footer() {
const [email, setEmail] = useState("")
const [isSubscribed, setIsSubscribed] = useState(false)
const sectionRef = useRef<HTMLElement>(null)
const [isVisible, setIsVisible] = useState(false)
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setIsVisible(true)
}
},
{ threshold: 0.1 }
)
if (sectionRef.current) {
observer.observe(sectionRef.current)
}
return () => observer.disconnect()
}, [])
const handleSubscribe = (e: React.FormEvent) => {
e.preventDefault()
if (email) {
setIsSubscribed(true)
setEmail("")
setTimeout(() => setIsSubscribed(false), 3000)
}
}
return (
<footer ref={sectionRef} className="w-full bg-muted/20 relative overflow-hidden">
{/* Background decorations */}
<div className="absolute inset-0 gradient-mesh opacity-10" />
<div className="absolute top-0 left-1/4 w-96 h-96 bg-primary/10 rounded-full blur-3xl animate-float" style={{ animationDelay: '0s' }} />
<div className="absolute bottom-0 right-1/4 w-96 h-96 bg-accent/10 rounded-full blur-3xl animate-float" style={{ animationDelay: '5s' }} />
{/* Animated grid */}
<div className="absolute inset-0 opacity-5">
<div className="absolute inset-0 bg-[radial-gradient(circle_at_50%_50%,hsl(var(--primary))_1px,transparent_1px)] bg-size-[32px_32px]" />
</div>
<div className={`container py-14 md:py-16 lg:py-20 relative z-10 transition-all duration-1000 ${isVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-10'}`}>
<div className="grid grid-cols-1 gap-10 md:grid-cols-2 lg:grid-cols-5">
{/* Brand column */}
<div className="flex flex-col gap-4 lg:col-span-2 lg:pr-8">
<Link href="/" className="text-xl font-bold tracking-tight group inline-flex items-center gap-2">
<span className="group-hover:scale-105 transition-transform inline-block">
Nexa<span className="gradient-text">Flow</span>
</span>
<Sparkles className="w-4 h-4 text-primary opacity-0 group-hover:opacity-100 group-hover:rotate-12 transition-all duration-300" suppressHydrationWarning />
</Link>
<p className="text-sm text-muted-foreground leading-relaxed max-w-xs">
Building digital experiences that matter. We partner with forward-thinking companies to create impactful digital products.
</p>
{/* Social icons */}
<div className="flex gap-3 mt-2">
{socialLinks.map((social) => (
<Link
key={social.label}
href={social.href}
className={`flex h-10 w-10 items-center justify-center rounded-xl glass-card text-muted-foreground hover:scale-110 transition-all duration-300 group ${social.color}`}
aria-label={social.label}
>
<social.icon className="h-4 w-4 transition-transform duration-300 group-hover:scale-110" suppressHydrationWarning />
</Link>
))}
</div>
</div>
{/* Link columns */}
{footerLinks.map((section, i) => (
<div
key={section.title}
className="flex flex-col gap-4"
style={{ transitionDelay: `${i * 100}ms` }}
>
<h3 className="text-sm font-semibold text-foreground flex items-center gap-2">
<span className="w-1.5 h-1.5 rounded-full bg-primary" />
{section.title}
</h3>
<ul className="flex flex-col gap-3">
{section.links.map((link) => (
<li key={link.name}>
<Link
href={link.href}
className="text-sm text-muted-foreground hover:text-primary transition-colors duration-200 interactive-underline inline-block"
>
{link.name}
</Link>
</li>
))}
</ul>
</div>
))}
</div>
{/* Newsletter signup */}
<div className="mt-12 relative">
{/* Animated border */}
<div className="absolute -inset-0.5 rounded-3xl animated-border opacity-30" />
<div className="relative glass-card rounded-3xl p-6 md:p-8 overflow-hidden">
{/* Inner glow */}
<div className="absolute inset-0 bg-gradient-to-br from-primary/5 via-transparent to-accent/5" />
<div className="relative z-10 flex flex-col md:flex-row items-start md:items-center justify-between gap-6">
<div>
<h3 className="text-lg font-semibold mb-2 flex items-center gap-2">
<Mail className="w-5 h-5 text-primary" suppressHydrationWarning />
Stay in the loop
</h3>
<p className="text-sm text-muted-foreground">Get the latest insights on web development and design delivered to your inbox.</p>
</div>
<form className="flex w-full md:w-auto gap-3" onSubmit={handleSubscribe}>
<Input
type="email"
placeholder="you@example.com"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="w-full md:w-64 glass-card border-0 focus:ring-2 focus:ring-primary/50"
/>
<Button type="submit" className="shine-effect group">
{isSubscribed ? (
<span className="flex items-center gap-2">
<Sparkles className="w-4 h-4" suppressHydrationWarning />
Subscribed!
</span>
) : (
<span className="flex items-center">
Subscribe
<ArrowRight className="ml-2 w-4 h-4 group-hover:translate-x-1 transition-transform" suppressHydrationWarning />
</span>
)}
</Button>
</form>
</div>
{/* Shine effect */}
<div className="absolute inset-0 shine-effect pointer-events-none rounded-3xl" />
</div>
</div>
{/* Bottom bar */}
<div className="mt-14 border-t border-border/50 pt-8 flex flex-col md:flex-row justify-between items-center gap-4">
<p className="text-sm text-muted-foreground">
&copy; {new Date().getFullYear()} NexaFlow. All rights reserved.
</p>
<p className="text-sm text-muted-foreground flex items-center gap-1">
Designed with{" "}
<Heart className="w-4 h-4 text-red-500 fill-red-500 animate-pulse" suppressHydrationWarning />
{" "}by{" "}
<span className="text-primary font-medium">NexaFlow</span>
</p>
</div>
</div>
</footer>
)
}