Proof footer
Inverse color band that reprises testing, ingredients, dispatch, and guarantee, then ends on a clipped wordmark.
blockproofanytrust
$
npx shadcn@latest add @storekit/footer-prooffooter-proof
Live and interactive. Switch the brand in the frame header to see the same source under another token file.
Installation
$
npx shadcn@latest add @storekit/footer-proof$
pnpm dlx shadcn@latest add @storekit/footer-proof$
yarn dlx shadcn@latest add @storekit/footer-proof$
bunx --bun shadcn@latest add @storekit/footer-proofSource
components/storekit/footer/footer-proof.tsx
127 lines
"use client"
import { useEffect, useRef } from "react"
import { BadgeCheck, FileCheck2, PackageCheck, ShieldCheck } from "lucide-react"
import { cn } from "@/components/storekit/lib/cn"
/* Inverted band footer (ink fill, paper text: dark on light brands, light on
dark brands) that reprises the store's trust claims before the link columns,
then ends on an oversized wordmark clipped by the bottom edge. Trust points
read as a quiet ledger, not a stat banner. The only client code shrinks the
wordmark when a wide display face would overflow the width. */
type Point = { title: string; note: string; icon?: "tested" | "ingredients" | "dispatch" | "guarantee" }
type Column = { title: string; links: { label: string; href: string }[] }
const ring =
"outline-none focus-visible:ring-2 focus-visible:ring-sk-paper focus-visible:ring-offset-2 focus-visible:ring-offset-sk-ink"
const ICONS = { tested: BadgeCheck, ingredients: FileCheck2, dispatch: PackageCheck, guarantee: ShieldCheck }
export function FooterProof({
brandName = "Morrow",
points = [
{ title: "Third-party tested", note: "Results published for every batch", icon: "tested" },
{ title: "Clean ingredients", note: "No fillers, no artificial colors", icon: "ingredients" },
{ title: "24h dispatch", note: "Orders before 2pm, same day", icon: "dispatch" },
{ title: "30-day guarantee", note: "Even if the pouch is empty", icon: "guarantee" },
],
columns = [
{ title: "Shop", links: [{ label: "All products", href: "#shop" }, { label: "Powders", href: "#powders" }, { label: "Drinks", href: "#drinks" }] },
{ title: "Proof", links: [{ label: "Lab results", href: "#lab-results" }, { label: "Ingredients", href: "#ingredients" }, { label: "Quality", href: "#quality" }] },
{ title: "Support", links: [{ label: "Shipping", href: "#shipping" }, { label: "Returns", href: "#returns" }, { label: "Contact", href: "#contact" }] },
],
legal = "These statements have not been evaluated by the FDA. This product is not intended to diagnose, treat, cure, or prevent any disease.",
className,
}: {
brandName?: string
points?: Point[]
columns?: Column[]
legal?: string
className?: string
}) {
return (
<footer data-sk-section="footer" data-sk-variant="footer-proof" className={cn("relative overflow-hidden bg-sk-ink text-sk-paper", className)}>
<div className="mx-auto max-w-6xl px-4 pt-14 sm:px-8">
<ul className="grid grid-cols-1 gap-px overflow-hidden rounded-sk-card border border-sk-paper/10 bg-sk-paper/10 sm:grid-cols-2 lg:grid-cols-4">
{points.map((p) => {
const Icon = ICONS[p.icon ?? "tested"]
return (
<li key={p.title} className="flex items-start gap-3 bg-sk-ink p-5">
<Icon size={18} aria-hidden className="mt-0.5 shrink-0 text-sk-paper/60" />
<div>
<p className="text-[15px] font-semibold">{p.title}</p>
<p className="mt-1 text-[13px] leading-[1.5] text-sk-paper/60">{p.note}</p>
</div>
</li>
)
})}
</ul>
<div className="grid grid-cols-2 gap-x-6 gap-y-10 py-14 sm:grid-cols-3 md:grid-cols-[1.5fr_1fr_1fr_1fr]">
<div className="col-span-2 max-w-xs sm:col-span-3 md:col-span-1">
<p className="font-sk-display text-xl font-semibold leading-[1.1] tracking-[-0.02em] text-balance">Every batch tested. Every result published.</p>
<p className="mt-3 text-[13px] leading-[1.5] text-sk-paper/60">{legal}</p>
</div>
{columns.map((c) => (
<nav key={c.title} aria-label={c.title}>
<p className="font-sk-mono text-[11px] uppercase tracking-[0.14em] text-sk-paper/50">{c.title}</p>
<ul className="mt-3 grid">
{c.links.map((l) => (
<li key={l.href}>
<a href={l.href} className={cn("inline-flex min-h-10 items-center rounded-sk-btn text-[13px] text-sk-paper/70 transition-colors duration-200 hover:text-sk-paper", ring)}>
{l.label}
</a>
</li>
))}
</ul>
</nav>
))}
</div>
<div className="flex flex-wrap items-center justify-between gap-2 border-t border-sk-paper/10 py-5 text-[13px] text-sk-paper/50">
<p>© {new Date().getFullYear()} {brandName}</p>
<p className="font-sk-mono text-[11px] uppercase tracking-[0.14em]">Made in the USA</p>
</div>
</div>
<Wordmark name={brandName} />
</footer>
)
}
/** Oversized wordmark sized by container width, then shrunk to fit if the
style pack's display face is wider than the estimate. */
function Wordmark({ name }: { name: string }) {
const box = useRef<HTMLDivElement>(null)
const text = useRef<HTMLSpanElement>(null)
useEffect(() => {
const b = box.current
const t = text.current
if (!b || !t) return
const fit = () => {
t.style.transform = ""
const avail = b.clientWidth - 16
const w = t.scrollWidth
if (w > avail && w > 0) t.style.transform = `scale(${avail / w})`
}
fit()
const ro = new ResizeObserver(fit)
ro.observe(b)
document.fonts?.ready.then(fit).catch(() => {})
return () => ro.disconnect()
}, [name])
return (
<div ref={box} aria-hidden className="pointer-events-none flex select-none justify-center overflow-hidden px-2 [container-type:inline-size]">
<span
ref={text}
className="-mb-[0.18em] block origin-bottom whitespace-nowrap font-sk-display font-semibold leading-[0.8] text-sk-paper/10"
// Inline tracking beats the style pack's display tracking.
style={{ fontSize: `min(240px, calc(100cqw / ${Math.max(4, name.length * 0.55).toFixed(2)}))`, letterSpacing: "-0.04em" }}
>
{name}
</span>
</div>
)
}
Usage
Import from "@/components/storekit/footer/footer-proof" and pass your product data. The demo above exercises the full prop surface with sample values.