"use client";
import * as React from "react";
import { motion, useReducedMotion, useScroll, useSpring } from "motion/react";
import { ArrowUp, Mail, MessagesSquare, Rss, type LucideIcon } from "lucide-react";
import { cn } from "@/lib/utils";
export interface FooterMinimalProps {
brand?: string;
tagline?: string;
links?: { label: string; href?: string }[];
socials?: { label: string; href?: string; icon: LucideIcon }[];
copyright?: string;
backToTopLabel?: string;
/** Override what "back to top" does (default: smooth-scroll the window). */
onBackToTop?: () => void;
className?: string;
}
export function FooterMinimal({
brand = "Lumen",
tagline = "Calm software for busy teams.",
links = [
{ label: "Product", href: "#" },
{ label: "Pricing", href: "#" },
{ label: "Blog", href: "#" },
{ label: "Careers", href: "#" },
{ label: "Contact", href: "#" },
],
socials = [
{ label: "Community", icon: MessagesSquare, href: "#" },
{ label: "RSS feed", icon: Rss, href: "#" },
{ label: "Email", icon: Mail, href: "#" },
],
copyright = "© 2026 Lumen Labs. All rights reserved.",
backToTopLabel = "Back to top",
onBackToTop,
className,
}: FooterMinimalProps) {
const reduce = useReducedMotion();
const { scrollYProgress } = useScroll();
const progress = useSpring(scrollYProgress, { stiffness: 200, damping: 30 });
const toTop = () => {
if (onBackToTop) return onBackToTop();
window.scrollTo({ top: 0, behavior: reduce ? "auto" : "smooth" });
};
return (
<footer className={cn("w-full border-t bg-background text-foreground", className)}>
<div className="mx-auto max-w-6xl px-5 sm:px-8">
<div className="flex flex-col gap-8 py-10 md:flex-row md:items-center md:justify-between">
<div className="flex items-center gap-3">
<span aria-hidden className="grid size-9 place-items-center rounded-xl bg-linear-to-br from-amber-400 via-orange-500 to-rose-500 shadow-sm">
<span className="size-3.5 rounded-full bg-white/90" />
</span>
<div>
<p className="font-semibold tracking-tight">{brand}</p>
<p className="text-sm text-muted-foreground">{tagline}</p>
</div>
</div>
<nav aria-label="Footer">
<ul className="flex flex-wrap gap-x-7 gap-y-3">
{links.map((l) => (
<li key={l.label}>
<UnderlineLink href={l.href}>{l.label}</UnderlineLink>
</li>
))}
</ul>
</nav>
<button
type="button"
onClick={toTop}
className="group inline-flex w-fit items-center gap-3 rounded-full py-1 pl-1 pr-4 text-sm font-medium text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
>
<span className="relative grid size-10 place-items-center">
<svg viewBox="0 0 40 40" className="absolute inset-0 -rotate-90" aria-hidden>
<circle cx="20" cy="20" r="18.5" fill="none" stroke="var(--color-border)" strokeWidth="1.5" />
<motion.circle
cx="20"
cy="20"
r="18.5"
fill="none"
stroke="var(--color-foreground)"
strokeWidth="1.5"
strokeLinecap="round"
style={{ pathLength: progress }}
/>
</svg>
<span className="relative block h-4 w-4 overflow-hidden" aria-hidden>
<ArrowUp className="absolute inset-0 size-4 transition-transform duration-300 ease-out group-hover:-translate-y-5" />
<ArrowUp className="absolute inset-0 size-4 translate-y-5 transition-transform duration-300 ease-out group-hover:translate-y-0" />
</span>
</span>
{backToTopLabel}
</button>
</div>
<div className="flex flex-col-reverse gap-4 border-t py-6 text-sm text-muted-foreground sm:flex-row sm:items-center sm:justify-between">
<p>{copyright}</p>
<ul className="flex items-center gap-1">
{socials.map((s) => (
<li key={s.label}>
<a
href={s.href ?? "#"}
aria-label={s.label}
title={s.label}
className="grid size-9 place-items-center rounded-full transition hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
>
<s.icon className="size-4" aria-hidden />
</a>
</li>
))}
</ul>
</div>
</div>
</footer>
);
}
function UnderlineLink({ href, children }: { href?: string; children: React.ReactNode }) {
return (
<a
href={href ?? "#"}
className="group relative inline-block py-1 text-sm font-medium text-muted-foreground transition-colors rounded-sm hover:text-foreground focus-visible:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-4 focus-visible:ring-offset-background"
>
{children}
<span
aria-hidden
className="absolute inset-x-0 bottom-0 h-px origin-right scale-x-0 bg-current transition-transform duration-300 ease-out group-hover:origin-left group-hover:scale-x-100 group-focus-visible:origin-left group-focus-visible:scale-x-100"
/>
</a>
);
}