189 lines
6.3 KiB
TypeScript
189 lines
6.3 KiB
TypeScript
/**
|
|
* Premium 4-column footer w/ no duplicated nav links.
|
|
*
|
|
* Expected lib/content.ts shape:
|
|
*
|
|
* export const brand = {
|
|
* name: "BRAND",
|
|
* legalName: "Brand Legal LLC",
|
|
* phone: "00 000 0000",
|
|
* email: "info@example.com",
|
|
* instagram: "@brand_handle",
|
|
* };
|
|
* export const socials = {
|
|
* instagram: "https://www.instagram.com/brand_handle/",
|
|
* whatsapp: "https://api.whatsapp.com/send/?phone=000000000000&text&type=phone_number&app_absent=0",
|
|
* whatsappDisplay: "+00 00 000 0000",
|
|
* };
|
|
* export const credit = {
|
|
* agency: "YS Lootah Tech",
|
|
* url: "https://yslootahtech.com/",
|
|
* };
|
|
*/
|
|
import { Mail, Phone } from "lucide-react";
|
|
import { brand, socials, credit } from "@/lib/content";
|
|
import { WhatsAppLink } from "./WhatsAppLink";
|
|
import { AppBadge } from "./AppBadges";
|
|
|
|
function InstagramIcon({ className }: { className?: string }) {
|
|
return (
|
|
<svg
|
|
aria-hidden
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="1.6"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
className={className}
|
|
>
|
|
<rect x="3" y="3" width="18" height="18" rx="5" />
|
|
<circle cx="12" cy="12" r="4" />
|
|
<circle cx="17.5" cy="6.5" r="1.1" fill="currentColor" stroke="none" />
|
|
</svg>
|
|
);
|
|
}
|
|
|
|
type Link = { label: string; href: string };
|
|
|
|
type Props = {
|
|
navigationLinks: Link[];
|
|
serviceItems: Link[];
|
|
legalLinks: Link[];
|
|
/** Brand logo node (provide your own LogoMark) */
|
|
logo?: React.ReactNode;
|
|
};
|
|
|
|
export function Footer({ navigationLinks, serviceItems, legalLinks, logo }: Props) {
|
|
return (
|
|
<footer className="relative overflow-hidden border-t border-bone/10 bg-obsidian pb-8 pt-11 md:pb-10 md:pt-14 lg:pb-12 lg:pt-[72px]">
|
|
<div className="relative z-10 mx-auto max-w-[1480px] px-6 md:px-10">
|
|
<div className="grid gap-10 lg:grid-cols-12 lg:gap-12">
|
|
{/* Col 1 Brand + contact */}
|
|
<div className="space-y-5 lg:col-span-4">
|
|
<a href="/" className="inline-flex items-center gap-4">
|
|
{logo}
|
|
<span className="hidden font-display text-2xl tracking-[0.22em] text-bone sm:inline">
|
|
{brand.name}
|
|
</span>
|
|
</a>
|
|
<p className="max-w-md text-sm text-mist text-pretty md:text-base">
|
|
{brand.legalName}.
|
|
</p>
|
|
<div className="metallic-divider" />
|
|
<div className="space-y-2 text-sm text-mist">
|
|
<a
|
|
href={`tel:${brand.phone.replace(/\s/g, "")}`}
|
|
className="flex items-center gap-3 hover:text-gold-light"
|
|
>
|
|
<Phone className="size-4" />
|
|
{brand.phone}
|
|
</a>
|
|
<a
|
|
href={`mailto:${brand.email}`}
|
|
className="flex items-center gap-3 hover:text-gold-light"
|
|
>
|
|
<Mail className="size-4" />
|
|
{brand.email}
|
|
</a>
|
|
<WhatsAppLink
|
|
href={socials.whatsapp}
|
|
display={socials.whatsappDisplay}
|
|
ariaLabel={`Chat with ${brand.name} on WhatsApp`}
|
|
inline
|
|
/>
|
|
<a
|
|
href={socials.instagram}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="flex items-center gap-3 hover:text-gold-light"
|
|
>
|
|
<InstagramIcon className="size-4" />
|
|
Instagram · {brand.instagram}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Cols 2-4 */}
|
|
<div className="grid gap-8 sm:grid-cols-3 lg:col-span-8 lg:gap-10">
|
|
<FooterCol title="Navigation" links={navigationLinks} />
|
|
<FooterCol title="Services" links={serviceItems} />
|
|
<div>
|
|
<h4 className="text-[10px] font-medium uppercase tracking-[0.22em] text-gold-light">
|
|
Legal & App
|
|
</h4>
|
|
<ul className="mt-4 space-y-2.5">
|
|
{legalLinks.map((l) => (
|
|
<li key={l.label}>
|
|
<a
|
|
href={l.href}
|
|
className="text-sm text-mist transition-colors hover:text-bone"
|
|
>
|
|
{l.label}
|
|
</a>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
<div className="mt-5 flex flex-col items-start gap-2">
|
|
<AppBadge store="appstore" small />
|
|
<AppBadge store="googleplay" small />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-9 flex flex-col items-start justify-between gap-3 border-t border-bone/10 pt-5 text-xs uppercase tracking-[0.22em] text-mist md:mt-10 md:flex-row md:items-center md:gap-6">
|
|
<span>
|
|
© {new Date().getFullYear()} {brand.legalName}. All rights reserved.
|
|
</span>
|
|
</div>
|
|
|
|
<div className="mt-3 text-[11px] tracking-[0.04em] text-mist/60 md:text-xs">
|
|
Website designed & developed by{" "}
|
|
<a
|
|
href={credit.url}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-mist/80 underline decoration-gold/30 decoration-1 underline-offset-4 transition-colors duration-500 hover:text-gold-light hover:decoration-gold/70"
|
|
>
|
|
{credit.agency}
|
|
</a>
|
|
.
|
|
</div>
|
|
</div>
|
|
|
|
{/* Watermark contained inside footer */}
|
|
<div
|
|
aria-hidden
|
|
className="pointer-events-none absolute inset-x-0 bottom-0 z-0 flex select-none justify-center overflow-hidden"
|
|
>
|
|
<span className="translate-y-[18%] font-display text-[14vw] leading-none tracking-[-0.02em] text-bone/[0.025] md:text-[12vw]">
|
|
{brand.name}
|
|
</span>
|
|
</div>
|
|
</footer>
|
|
);
|
|
}
|
|
|
|
function FooterCol({ title, links }: { title: string; links: Link[] }) {
|
|
return (
|
|
<div>
|
|
<h4 className="text-[10px] font-medium uppercase tracking-[0.22em] text-gold-light">
|
|
{title}
|
|
</h4>
|
|
<ul className="mt-4 space-y-2.5">
|
|
{links.map((l) => (
|
|
<li key={l.label}>
|
|
<a
|
|
href={l.href}
|
|
className="text-sm text-mist transition-colors hover:text-bone"
|
|
>
|
|
{l.label}
|
|
</a>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
);
|
|
}
|