Files
assetx/landingpage/components/Footer.tsx

182 lines
8.6 KiB
TypeScript
Raw Permalink Normal View History

'use client';
import { useState, useEffect, useRef } from 'react';
import Image from 'next/image';
import { Link, Button } from '@heroui/react';
import { Github, Mail } from 'lucide-react';
import { motion } from 'framer-motion';
const XIcon = ({ color }: { color: string }) => (
<svg width="24" height="24" viewBox="0 0 24 24" fill={color}>
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.744l7.73-8.835L1.254 2.25H8.08l4.253 5.622zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>
</svg>
);
const DiscordIcon = ({ color }: { color: string }) => (
<svg width="24" height="24" viewBox="0 0 24 24" fill={color}>
<path d="M20.317 4.492c-1.53-.69-3.17-1.2-4.885-1.49a.075.075 0 0 0-.079.036c-.21.369-.444.85-.608 1.23a18.566 18.566 0 0 0-5.487 0 12.36 12.36 0 0 0-.617-1.23A.077.077 0 0 0 8.562 3c-1.714.29-3.354.8-4.885 1.491a.07.07 0 0 0-.032.027C.533 9.093-.32 13.555.099 17.961a.08.08 0 0 0 .031.055 20.03 20.03 0 0 0 5.993 2.98.078.078 0 0 0 .084-.026 13.83 13.83 0 0 0 1.226-1.963.074.074 0 0 0-.041-.104 13.175 13.175 0 0 1-1.872-.878.075.075 0 0 1-.008-.125c.126-.093.252-.19.372-.287a.075.075 0 0 1 .078-.01c3.927 1.764 8.18 1.764 12.061 0a.075.075 0 0 1 .079.009c.12.098.245.195.372.288a.075.075 0 0 1-.006.125c-.598.344-1.22.635-1.873.877a.075.075 0 0 0-.041.105c.36.687.772 1.341 1.225 1.962a.077.077 0 0 0 .084.028 19.963 19.963 0 0 0 6.002-2.981.076.076 0 0 0 .032-.054c.5-5.094-.838-9.52-3.549-13.442a.06.06 0 0 0-.031-.028zM8.02 15.278c-1.182 0-2.157-1.069-2.157-2.38 0-1.312.956-2.38 2.157-2.38 1.21 0 2.176 1.077 2.157 2.38 0 1.312-.956 2.38-2.157 2.38zm7.975 0c-1.183 0-2.157-1.069-2.157-2.38 0-1.312.955-2.38 2.157-2.38 1.21 0 2.176 1.077 2.157 2.38 0 1.312-.946 2.38-2.157 2.38z"/>
</svg>
);
import { useLanguage } from '@/contexts/LanguageContext';
import { useTheme } from '@/contexts/ThemeContext';
export default function Footer() {
const { t } = useLanguage();
const { theme } = useTheme();
const isDark = theme === 'dark';
const [animate, setAnimate] = useState(false);
const footerRef = useRef<HTMLElement>(null);
useEffect(() => {
const currentRef = footerRef.current;
if (!currentRef) return;
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
setAnimate(true);
observer.disconnect();
}
},
{ threshold: 0.1 }
);
observer.observe(currentRef);
return () => observer.disconnect();
}, []);
const socialIcons = [
{ render: (c: string) => <XIcon color={c} />, alt: 'X' },
{ render: (c: string) => <Github size={24} color={c} />, alt: 'GitHub' },
{ render: (c: string) => <DiscordIcon color={c} />, alt: 'Discord' },
{ render: (c: string) => <Mail size={24} color={c} />, alt: 'Email' },
];
return (
<footer ref={footerRef} className="w-full flex flex-col items-center border-t bg-bg-base border-border-normal">
{/* Main Footer Content */}
<div className="w-full max-w-[1440px] 2xl:max-w-[1760px] 3xl:max-w-[2200px] px-4 md:px-6 2xl:px-10 3xl:px-16 py-10 md:py-20 flex flex-col md:flex-row gap-8">
{/* Left Section */}
<motion.div
className="flex flex-col gap-4 md:gap-6 md:w-[389.33px]"
initial={{ opacity: 0, x: -24 }}
animate={animate ? { opacity: 1, x: 0 } : {}}
transition={{ duration: 0.6, ease: 'easeOut' }}
>
{/* Logo */}
<div className="flex items-center md:items-center">
<Image
src="/logo0.svg"
alt="AssetX Logo"
width={160}
height={40}
className="w-[160px] h-auto"
style={{ filter: isDark ? 'invert(1) brightness(1.2)' : 'none' }}
/>
</div>
{/* Address + Social Icons */}
<div className="flex flex-col gap-3 md:gap-6">
<div
className="text-text-tertiary text-left font-domine"
style={{ fontSize: '14px', lineHeight: '150%', fontWeight: 400 }}
>
G/F, Hong Kong Museum Of Art, 10 Salisbury
<br />
Rd, Tsim Sha Tsui, HongKong
</div>
<div className="flex flex-row gap-1 md:gap-2 items-center">
{socialIcons.map((icon, index) => (
<Button key={index} isIconOnly variant="light" className="min-w-10 w-10 h-10">
{icon.render(isDark ? '#9ca3af' : '#6b7280')}
</Button>
))}
</div>
</div>
</motion.div>
{/* Right Section */}
<div className="flex flex-col md:flex-row md:justify-between md:flex-1 gap-6 md:gap-0">
{/* Products + Resources */}
<div className="flex flex-row gap-4 md:contents">
<motion.div
className="flex flex-col gap-4 flex-1 md:flex-none md:w-[178.67px]"
initial={{ opacity: 0, y: 24 }}
animate={animate ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, ease: 'easeOut', delay: 0.15 }}
>
<h3 className="font-domine font-bold text-base text-text-primary" style={{ lineHeight: '150%' }}>
{t('footer.products')}
</h3>
<div className="flex flex-col gap-2">
{[1, 2, 3, 4, 5].map((num) => (
<Link key={num} href="#" className="font-domine text-sm text-text-tertiary hover:text-text-primary" style={{ lineHeight: '150%' }}>
{t(`footer.product${num}`)}
</Link>
))}
</div>
</motion.div>
<motion.div
className="flex flex-col gap-4 flex-1 md:flex-none md:w-[178.67px]"
initial={{ opacity: 0, y: 24 }}
animate={animate ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, ease: 'easeOut', delay: 0.25 }}
>
<h3 className="font-domine font-bold text-base text-text-primary" style={{ lineHeight: '150%' }}>
{t('footer.resources')}
</h3>
<div className="flex flex-col gap-2">
{[1, 2, 3, 4, 5].map((num) => (
<Link key={num} href="#" className="font-domine text-sm text-text-tertiary hover:text-text-primary" style={{ lineHeight: '150%' }}>
{t(`footer.resource${num}`)}
</Link>
))}
</div>
</motion.div>
</div>
{/* Company */}
<motion.div
className="flex flex-col gap-4 md:w-[178.67px]"
initial={{ opacity: 0, y: 24 }}
animate={animate ? { opacity: 1, y: 0 } : {}}
transition={{ duration: 0.6, ease: 'easeOut', delay: 0.35 }}
>
<h3 className="font-domine font-bold text-base text-text-primary" style={{ lineHeight: '150%' }}>
{t('footer.company')}
</h3>
<div className="flex flex-col gap-2">
{[1, 2, 3, 4].map((num) => (
<Link key={num} href="#" className="font-domine text-sm text-text-tertiary hover:text-text-primary" style={{ lineHeight: '150%' }}>
{t(`footer.company${num}`)}
</Link>
))}
</div>
</motion.div>
</div>
</div>
{/* Bottom Section */}
<motion.div
className="w-full max-w-[1440px] 2xl:max-w-[1760px] 3xl:max-w-[2200px] border-t border-border-subtle px-4 md:px-6 2xl:px-10 3xl:px-16 py-6 md:py-8 flex flex-col md:flex-row items-center md:items-center justify-between gap-3 md:gap-0"
initial={{ opacity: 0 }}
animate={animate ? { opacity: 1 } : {}}
transition={{ duration: 0.6, ease: 'easeOut', delay: 0.5 }}
>
<div className="text-text-tertiary font-domine text-sm text-center md:text-left" style={{ lineHeight: '150%' }}>
{t('footer.copyright')}
</div>
<div className="flex flex-row gap-6">
<Link href="#" className={`font-domine text-sm ${isDark ? 'text-[#9ca1af] hover:text-[#fafafa]' : 'text-[#9ca1af] hover:text-[#111827]'}`} style={{ lineHeight: '150%' }}>
{t('footer.privacy')}
</Link>
<Link href="#" className={`font-domine text-sm ${isDark ? 'text-[#9ca1af] hover:text-[#fafafa]' : 'text-[#9ca1af] hover:text-[#111827]'}`} style={{ lineHeight: '150%' }}>
{t('footer.terms')}
</Link>
</div>
</motion.div>
</footer>
);
}