Footer

Footer 02 — Minimal Watermark

Compact single-row footer with logo, links and socials above a huge fading decorative watermark wordmark.

$ npx shadcn@latest add @ludusvibe/footer-02
Open in v0

Code

Installed to components/sections/footer-02.tsx — it's yours to edit.

"use client"

import * as React from "react"

import { buttonVariants } from "@/components/ui/button"
import { Reveal } from "@/components/ludus/reveal"
import { cn } from "@/lib/utils"

function XIcon(props: React.SVGProps<SVGSVGElement>) {
  return (
    <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden {...props}>
      <path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231 5.45-6.231Zm-1.161 17.52h1.833L7.084 4.126H5.117l11.966 15.644Z" />
    </svg>
  )
}

function GitHubIcon(props: React.SVGProps<SVGSVGElement>) {
  return (
    <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden {...props}>
      <path d="M12 .5C5.65.5.5 5.65.5 12c0 5.08 3.29 9.39 7.86 10.91.58.11.79-.25.79-.55 0-.27-.01-1.17-.02-2.12-3.2.7-3.87-1.36-3.87-1.36-.52-1.33-1.28-1.68-1.28-1.68-1.04-.71.08-.7.08-.7 1.15.08 1.76 1.19 1.76 1.19 1.03 1.75 2.69 1.25 3.35.95.1-.75.4-1.25.72-1.54-2.55-.29-5.23-1.28-5.23-5.68 0-1.26.45-2.28 1.19-3.09-.12-.29-.52-1.46.11-3.05 0 0 .97-.31 3.18 1.18a11.1 11.1 0 0 1 5.8 0c2.2-1.49 3.17-1.18 3.17-1.18.63 1.59.23 2.76.11 3.05.74.81 1.19 1.83 1.19 3.09 0 4.41-2.69 5.38-5.25 5.66.41.36.78 1.05.78 2.12 0 1.53-.01 2.76-.01 3.14 0 .3.2.66.8.55A11.51 11.51 0 0 0 23.5 12C23.5 5.65 18.35.5 12 .5Z" />
    </svg>
  )
}

function LinkedInIcon(props: React.SVGProps<SVGSVGElement>) {
  return (
    <svg viewBox="0 0 24 24" fill="currentColor" aria-hidden {...props}>
      <path d="M20.45 20.45h-3.55v-5.57c0-1.33-.03-3.04-1.85-3.04-1.86 0-2.14 1.45-2.14 2.94v5.67H9.35V9h3.41v1.56h.05c.48-.9 1.64-1.85 3.37-1.85 3.6 0 4.27 2.37 4.27 5.46v6.28ZM5.34 7.43a2.06 2.06 0 1 1 0-4.12 2.06 2.06 0 0 1 0 4.12ZM7.12 20.45H3.56V9h3.56v11.45ZM22.22 0H1.77C.79 0 0 .77 0 1.72v20.55C0 23.23.79 24 1.77 24h20.45c.98 0 1.78-.77 1.78-1.73V1.72C24 .77 23.2 0 22.22 0Z" />
    </svg>
  )
}

type FooterLink = { label: string; href: string }
type SocialLink = { label: string; href: string; icon: React.ReactNode }

export type Footer02Props = {
  /** Text logo — pass a string or any node. */
  logo?: React.ReactNode
  logoHref?: string
  links?: FooterLink[]
  socialLinks?: SocialLink[]
  copyright?: string
  /** Huge decorative wordmark rendered behind the bottom edge. */
  watermark?: string
  className?: string
}

export function Footer02({
  logo = "Lumen",
  logoHref = "#",
  links = [
    { label: "Features", href: "#" },
    { label: "Pricing", href: "#" },
    { label: "Blog", href: "#" },
    { label: "Docs", href: "#" },
    { label: "Contact", href: "#" },
  ],
  socialLinks = [
    { label: "X", href: "#", icon: <XIcon /> },
    { label: "GitHub", href: "#", icon: <GitHubIcon /> },
    { label: "LinkedIn", href: "#", icon: <LinkedInIcon /> },
  ],
  copyright = `© ${new Date().getFullYear()} Lumen, Inc. All rights reserved.`,
  watermark = "Lumen",
  className,
}: Footer02Props) {
  return (
    <footer
      className={cn("relative overflow-hidden border-t bg-background", className)}
    >
      <div className="relative z-10 mx-auto max-w-6xl px-6 pt-12">
        <Reveal>
          <div className="flex flex-col items-center justify-between gap-6 md:flex-row">
            <a
              href={logoHref}
              className="flex items-center gap-2.5 font-heading text-lg font-semibold tracking-tight"
            >
              <span
                aria-hidden
                className="size-4 rounded-full bg-gradient-to-br from-primary to-primary/40 ring-4 ring-primary/15"
              />
              {logo}
            </a>

            <div className="flex flex-wrap items-center justify-center gap-x-6 gap-y-2">
              {links.map((link) => (
                <a
                  key={link.label}
                  href={link.href}
                  className="text-sm text-muted-foreground transition-colors hover:text-foreground"
                >
                  {link.label}
                </a>
              ))}
            </div>

            <div className="flex items-center gap-1">
              {socialLinks.map((social) => (
                <a
                  key={social.label}
                  href={social.href}
                  aria-label={social.label}
                  className={cn(
                    buttonVariants({ variant: "ghost", size: "icon-sm" }),
                    "rounded-full text-muted-foreground hover:text-foreground"
                  )}
                >
                  {social.icon}
                </a>
              ))}
            </div>
          </div>

          <p className="mt-8 text-center text-xs text-muted-foreground">
            {copyright}
          </p>
        </Reveal>
      </div>

      <div aria-hidden className="pointer-events-none relative mt-2 select-none">
        <span className="-mb-[0.22em] block text-center font-heading text-[18vw] leading-none font-bold tracking-tighter text-foreground/5 [mask-image:linear-gradient(to_bottom,black,transparent_85%)]">
          {watermark}
        </span>
        <div className="absolute inset-x-0 bottom-0 h-1/2 bg-gradient-to-t from-primary/5 to-transparent" />
      </div>
    </footer>
  )
}