Preview
Live interactive preview.
Installation
Add this component to your project using the CLI:
terminal
npx -y vui-registry-cli-v1@latest add minimal-rich-footerSource Code
minimal-rich-footer.tsx
"use client";
import React, { useState } from "react";
import { ArrowUpRight } from "lucide-react";
export default function MinimalRichFooter() {
const [hoveredLink, setHoveredLink] = useState<string | null>(null);
const links = [
{ label: "Components", group: "Platform" },
{ label: "Templates", group: "Platform" },
{ label: "Pricing", group: "Platform" },
{ label: "Showcase", group: "Platform" },
{ label: "Documentation", group: "Developers" },
{ label: "API Reference", group: "Developers" },
{ label: "Changelog", group: "Developers" },
{ label: "GitHub", group: "Developers" },
{ label: "Privacy Policy", group: "Legal" },
{ label: "Terms of Service", group: "Legal" },
{ label: "Cookie Policy", group: "Legal" },
];
return (
<footer className="w-full bg-[#050505] text-white overflow-hidden relative selection:bg-white/20 selection:text-white">
{/* Absolute top thin border */}
<div className="absolute top-0 left-0 w-full h-[1px] bg-gradient-to-r from-transparent via-white/20 to-transparent" />
{/* Grainy Noise Overlay - Essential for premium Vercel/Linear feel */}
<div className="absolute inset-0 bg-[url('https://grainy-gradients.vercel.app/noise.svg')] opacity-20 mix-blend-overlay pointer-events-none" />
{/* Subtle Glows */}
<div className="absolute top-0 left-1/2 -translate-x-1/2 w-[800px] h-[400px] bg-white/[0.03] rounded-full blur-[120px] pointer-events-none" />
<div className="max-w-7xl mx-auto px-6 pt-32 pb-12 flex flex-col gap-16 relative z-10">
{/* Links Grid */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-12 md:gap-4">
<div className="col-span-2 md:col-span-1 flex flex-col justify-between">
<div className="flex flex-col gap-4">
<h3 className="text-sm font-bold text-white tracking-tight">Stay updated</h3>
<p className="text-sm text-white/50 leading-relaxed max-w-[240px]">
Subscribe to our newsletter for the latest component releases.
</p>
<div className="relative mt-2 max-w-[240px]">
<input
type="email"
placeholder="Email address"
className="w-full bg-white/5 border border-white/10 rounded-lg px-4 py-2.5 text-sm text-white placeholder:text-white/30 focus:outline-none focus:ring-1 focus:ring-white/30 transition-all"
/>
<button className="absolute right-1 top-1 bottom-1 px-3 bg-white text-black rounded-md text-xs font-semibold hover:bg-white/90 transition-colors">
Join
</button>
</div>
</div>
</div>
{["Platform", "Developers", "Legal"].map((group) => (
<div key={group} className="flex flex-col gap-6">
<h4 className="text-xs font-bold text-white/40 uppercase tracking-[0.2em]">{group}</h4>
<div className="flex flex-col gap-3">
{links.filter(l => l.group === group).map(link => (
<a
key={link.label}
href="#"
onMouseEnter={() => setHoveredLink(link.label)}
onMouseLeave={() => setHoveredLink(null)}
className="group flex items-center gap-2 text-sm font-medium text-white/70 hover:text-white transition-colors w-fit"
>
<span className="relative">
{link.label}
<span className="absolute left-0 bottom-0 w-full h-[1px] bg-white origin-left scale-x-0 group-hover:scale-x-100 transition-transform duration-300 ease-out" />
</span>
<ArrowUpRight className={`w-3 h-3 text-white/40 transition-all duration-300 ${hoveredLink === link.label ? "opacity-100 translate-x-0.5 -translate-y-0.5" : "opacity-0 -translate-x-2 translate-y-2"}`} />
</a>
))}
</div>
</div>
))}
</div>
{/* Bottom */}
<div className="flex flex-col md:flex-row justify-between items-center gap-4 text-xs font-medium text-white/40 pt-8 border-t border-white/10">
<p>© {new Date().getFullYear()} Velocity UI. All rights reserved.</p>
<div className="flex gap-8">
{["Twitter", "LinkedIn", "GitHub"].map((social) => (
<a key={social} href="#" className="hover:text-white transition-colors">
{social}
</a>
))}
</div>
</div>
</div>
</footer>
);
}
Dependencies
framer-motion: latest