Footer

Full site footer with link columns, newsletter and socials.

Installation

  1. Install the dependencies

    $ npm i motion lucide-react
  2. Copy the source into components/ui/footer-section.tsx

    components/ui/footer-section.tsx
    "use client";
    
    import { motion } from "motion/react";
    import { ArrowRight, Github, Hexagon, Linkedin, Twitter } from "lucide-react";
    
    const columns = {
      Product: ["Features", "Pricing", "Integrations", "Changelog"],
      Company: ["About", "Careers", "Blog", "Press"],
      Resources: ["Docs", "Guides", "API", "Status"],
    };
    
    export function FooterSection({ brand = "Acme" }: { brand?: string }) {
      return (
        <footer className="w-full rounded-3xl border border-zinc-200 bg-white px-8 pb-8 pt-12">
          <div className="grid gap-10 lg:grid-cols-[1.5fr_1fr_1fr_1fr]">
            <div>
              <span className="flex items-center gap-2 font-semibold text-zinc-900">
                <Hexagon className="size-5 fill-zinc-900" /> {brand}
              </span>
              <p className="mt-3 max-w-xs text-sm text-zinc-500">Tools for teams that ship. Get product updates once a month.</p>
              <form onSubmit={(e) => e.preventDefault()} className="mt-5 flex max-w-xs gap-2">
                <input type="email" placeholder="[email protected]" aria-label="Email" className="min-w-0 flex-1 rounded-lg border border-zinc-200 px-3 py-2 text-sm outline-none focus:border-zinc-400" />
                <button aria-label="Subscribe" className="grid size-9 shrink-0 place-items-center rounded-lg bg-zinc-900 text-white hover:bg-zinc-800">
                  <ArrowRight className="size-4" />
                </button>
              </form>
            </div>
            {Object.entries(columns).map(([title, links]) => (
              <div key={title}>
                <p className="text-sm font-semibold text-zinc-900">{title}</p>
                <ul className="mt-4 space-y-2.5">
                  {links.map((l) => (
                    <li key={l}>
                      <a href="#" className="group inline-flex items-center gap-1 text-sm text-zinc-500 transition-colors hover:text-zinc-900">
                        {l}
                        <ArrowRight className="size-3 -translate-x-1 opacity-0 transition-all group-hover:translate-x-0 group-hover:opacity-100" />
                      </a>
                    </li>
                  ))}
                </ul>
              </div>
            ))}
          </div>
          <div className="mt-12 flex flex-wrap items-center justify-between gap-4 border-t border-zinc-100 pt-6 text-sm text-zinc-500">
            <span>© {new Date().getFullYear()} {brand}, Inc.</span>
            <div className="flex gap-2">
              {[Twitter, Github, Linkedin].map((Icon, i) => (
                <motion.a key={i} href="#" aria-label="Social link" whileHover={{ y: -3 }} className="grid size-9 place-items-center rounded-full border border-zinc-200 text-zinc-600 hover:text-zinc-900">
                  <Icon className="size-4" />
                </motion.a>
              ))}
            </div>
          </div>
        </footer>
      );
    }
    
    export default function Demo() {
      return (
        <div className="w-full max-w-5xl">
          <FooterSection />
        </div>
      );
    }
    
  3. Use it

    The file exports the component and a Demo showing typical usage. Import whichever you need.