A studio's footer whose wordmark turns to whichever link you point at or tab to, and back to the name when you leave.
registry/demos/echo-reel-footer-demo.tsx
"use client";
import * as React from "react";
import { EchoReel } from "@/components/ui/echo-reel";
const BRAND = "Fieldwork";
const LINKS = [
{ label: "Work", href: "#work" },
{ label: "Studio", href: "#studio" },
{ label: "Journal", href: "#journal" },
{ label: "Contact", href: "#contact" },
];
const WORDS = [BRAND, ...LINKS.map((link) => link.label)];
export function EchoReelFooterDemo() {
const [word, setWord] = React.useState(0);
const back = React.useRef<number | undefined>(undefined);
const show = (index: number) => {
window.clearTimeout(back.current);
setWord(index);
};
// Wait a beat before going back to the name, so moving between links
// doesn't turn the reel twice.
const release = () => {
window.clearTimeout(back.current);
back.current = window.setTimeout(() => setWord(0), 250);
};
React.useEffect(() => () => window.clearTimeout(back.current), []);
return (
<footer className="w-full max-w-4xl overflow-hidden rounded-3xl border border-[#0b0b0d]/10 bg-white px-5 pt-8 pb-5 text-[#0b0b0d] sm:px-10 dark:border-white/10 dark:bg-[#07080c] dark:text-[#f4f4f6]">
<div className="flex flex-wrap items-start justify-between gap-x-10 gap-y-6">
<div className="max-w-[17rem]">
<p className="flex items-center gap-2 text-sm font-semibold tracking-tight">
<span aria-hidden className="size-2.5 rounded-full bg-[#c6ff4f] ring-1 ring-[#0b0b0d]/15 dark:ring-0" />
Fieldwork Studio
</p>
<p className="mt-2 text-sm leading-relaxed text-[#0b0b0d]/60 dark:text-[#f4f4f6]/60">
Brand, product and type for companies that ship. Lisbon and remote.
</p>
<a
href="#contact"
className="mt-3 inline-block rounded text-sm font-medium underline decoration-[#0b0b0d]/25 underline-offset-4 hover:decoration-current focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current dark:decoration-[#f4f4f6]/30"
>
hello@fieldwork.studio
</a>
</div>
<nav aria-label="Footer" onPointerLeave={release} onBlur={release}>
<ul className="grid grid-cols-2 gap-x-10 gap-y-1 text-sm font-medium">
{LINKS.map((link, i) => (
<li key={link.href}>
<a
href={link.href}
onPointerEnter={() => show(i + 1)}
onFocus={() => show(i + 1)}
className="-mx-1.5 inline-flex rounded-md px-1.5 py-1 text-[#0b0b0d]/70 transition-colors duration-150 hover:text-[#0b0b0d] focus-visible:outline-2 focus-visible:outline-current dark:text-[#f4f4f6]/70 dark:hover:text-[#c6ff4f]"
>
{link.label}
</a>
</li>
))}
</ul>
</nav>
</div>
<EchoReel
words={WORDS}
value={word}
onValueChange={(index) => setWord(index)}
interval={false}
className="mt-8 text-[#0b0b0d] dark:text-[#c6ff4f]"
/>
<div className="mt-3 flex flex-wrap items-center justify-between gap-2 border-t border-[#0b0b0d]/10 pt-4 text-xs text-[#0b0b0d]/55 dark:border-white/10 dark:text-[#f4f4f6]/50">
<span>© 2026 Fieldwork Studio Lda.</span>
<a href="#top" className="rounded hover:text-current focus-visible:outline-2 focus-visible:outline-current">
Back to top ↑
</a>
</div>
</footer>
);
}
Live preview, examples and props: https://keyframeui.com/components/echo-reel#echo-reel-footer-demo