Skip to content
All Taste components

Footer

Footer — dark with newsletter

A dark footer with a newsletter sign-up beside three link columns, social links and the legal line.

always-dark surface · email sign-up · 3 link columns · socials

import { Instagram, Linkedin, Twitter, Youtube } from "lucide-react";

// Uses the neutral ramp from the Taste preset so the footer stays dark in
// both light and dark mode.
const columns = [
  { title: "Product", links: [["Invoices", "/invoices"], ["Payments", "/payments"], ["Reminders", "/reminders"], ["Recurring billing", "/recurring"], ["Pricing", "/pricing"]] },
  { title: "Resources", links: [["Help centre", "/help"], ["Invoice templates", "/templates"], ["Guides", "/guides"], ["Blog", "/blog"], ["Status", "/status"]] },
  { title: "Company", links: [["About", "/about"], ["Careers", "/careers"], ["Customers", "/customers"], ["Press", "/press"], ["Contact", "/contact"]] },
];

const socials = [
  { label: "X", href: "#", icon: Twitter },
  { label: "LinkedIn", href: "#", icon: Linkedin },
  { label: "Instagram", href: "#", icon: Instagram },
  { label: "YouTube", href: "#", icon: Youtube },
];

export function FooterDarkNewsletter({ subscribeAction = "/api/subscribe" }: { subscribeAction?: string }) {
  return (
    <footer className="border-t border-neutral-800 bg-neutral-950 px-5 pb-7 pt-12 font-sans text-neutral-50 sm:px-10 sm:pt-16">
      <div className="mx-auto max-w-6xl">
        <div className="grid gap-10 lg:grid-cols-[1.2fr_1.8fr] lg:gap-16">
          <div className="grid content-start gap-3.5">
            <a href="/" className="inline-flex items-center gap-2 text-base font-semibold tracking-tight">
              <span className="size-6 rounded-sm bg-primary" aria-hidden />Tallybook
            </a>
            <p className="text-sm leading-relaxed text-neutral-400">One email a month with new features and a practical tip on getting paid.</p>
            <form action={subscribeAction} method="post" className="grid gap-2">
              <label htmlFor="footer-email" className="text-[13px] font-medium text-neutral-200">Email address</label>
              <div className="flex flex-wrap gap-2">
                <input id="footer-email" name="email" type="email" required autoComplete="email" placeholder="you@example.com"
                  className="h-[42px] min-w-0 flex-[1_1_200px] rounded border border-neutral-700 bg-neutral-900 px-3 text-sm text-neutral-50 outline-none placeholder:text-neutral-500 focus:border-neutral-400" />
                <button type="submit" className="h-[42px] shrink-0 rounded bg-neutral-50 px-4 text-sm font-medium text-neutral-950 transition hover:bg-neutral-200">Subscribe</button>
              </div>
              <p className="text-[13px] text-neutral-400">No spam. Unsubscribe any time.</p>
            </form>
          </div>
          <nav aria-label="Footer" className="grid grid-cols-2 gap-x-5 gap-y-8 sm:grid-cols-3">
            {columns.map((col) => (
              <div key={col.title}>
                <h2 className="mb-3.5 text-[13px] font-semibold">{col.title}</h2>
                <ul className="grid gap-2.5">
                  {col.links.map(([label, href]) => (
                    <li key={label}><a href={href} className="text-[13.5px] text-neutral-400 transition hover:text-neutral-50">{label}</a></li>
                  ))}
                </ul>
              </div>
            ))}
          </nav>
        </div>

        <div className="mt-12 flex flex-wrap items-center justify-between gap-3 border-t border-neutral-800 pt-6 text-[13px] text-neutral-500">
          <p>© {new Date().getFullYear()} Tallybook Ltd. · <a href="/terms" className="hover:text-neutral-50">Terms</a> · <a href="/privacy" className="hover:text-neutral-50">Privacy</a></p>
          <div className="flex gap-1">
            {socials.map(({ label, href, icon: Icon }) => (
              <a key={label} href={href} aria-label={"Tallybook on " + label} className="grid size-8 place-items-center rounded text-neutral-400 transition hover:bg-neutral-800 hover:text-neutral-50">
                <Icon className="size-4" aria-hidden />
              </a>
            ))}
          </div>
        </div>
      </div>
    </footer>
  );
}

The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.