A studio's work index. Point at a project: its photo opens at the pointer and trails it. Move down the list and each photo wipes in from the top; move up and it comes from the bottom. Sweep fast to flip through them. Tab through the rows to see each photo without a mouse.
@keyframeui
registry/demos/hover-preview-demo.tsx
import { HoverPreview, HoverPreviewItem } from "@/components/ui/hover-preview";
const projects = [
{ name: "Northwind", category: "Branding", year: 2025, photo: "1561070791-2526d30994b5" },
{ name: "Lumen Studio", category: "Web", year: 2024, photo: "1618005182384-a83a8bd57fbe" },
{ name: "Atlas Bank", category: "Product", year: 2024, photo: "1460925895917-afdab827c52f" },
{ name: "Field Notes", category: "Editorial", year: 2023, photo: "1455390582262-044cdead277a" },
{ name: "Halden House", category: "Architecture", year: 2023, photo: "1600585154340-be6161a56a0c" },
{ name: "Sona Audio", category: "Campaign", year: 2022, photo: "1505740420928-5e560c06d30e" },
{ name: "Maison Vert", category: "Interiors", year: 2022, photo: "1618221195710-dd6b41faaea6" },
];
const photo = (id: string, width: number, height: number) =>
`https://images.unsplash.com/photo-${id}?auto=format&fit=crop&w=${width}&h=${height}&q=80`;
const slug = (name: string) => name.toLowerCase().replace(/\s+/g, "-");
export function HoverPreviewDemo() {
return (
<section className="w-full max-w-3xl">
<div className="mb-4 flex items-end justify-between gap-4">
<p className="font-mono text-xs tracking-widest text-zinc-500 uppercase">Selected work</p>
<p className="font-mono text-xs text-zinc-500 tabular-nums">2022–2025</p>
</div>
<HoverPreview className="border-t border-zinc-200 dark:border-zinc-800">
{projects.map((project) => (
<HoverPreviewItem
key={project.name}
href={`#${slug(project.name)}`}
image={photo(project.photo, 640, 480)}
thumbnail={photo(project.photo, 120, 120)}
className="border-b border-zinc-200 py-4 sm:py-5 dark:border-zinc-800"
>
<span className="flex-1 text-2xl font-medium tracking-tight text-zinc-900 sm:text-5xl dark:text-zinc-50">
{project.name}
</span>
<span className="text-xs text-zinc-500 tabular-nums sm:text-sm">
{project.category} · {project.year}
</span>
</HoverPreviewItem>
))}
</HoverPreview>
</section>
);
}
Live preview, examples and props: https://keyframeui.com/components/hover-preview#hover-preview-demo






















