A brand studio's header over ink in water. The ink waits in black and white; moving through it paints the color in, and the stroke closes back over about half a second. On a phone the brush drifts by itself. The nav links stay clickable over the picture.
@keyframeui
registry/demos/paint-reveal-demo.tsx
import { PaintReveal } from "@/components/ui/paint-reveal";
const ink = (grade = "") =>
`https://images.unsplash.com/photo-1541701494587-cb58502866ab?auto=format&fit=crop&w=2000&h=1250&q=80${grade}`;
export function PaintRevealDemo() {
return (
<PaintReveal
src={ink("&sat=-100&con=10")}
alt="Clouds of ink drifting through water, in black and white"
revealSrc={ink()}
revealAlt="The same ink clouds in red, orange and electric blue"
className="h-[var(--demo-height,34rem)] w-full rounded-xl border border-zinc-200 bg-black text-white dark:border-zinc-800"
>
<div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-black/75 via-transparent to-black/40" />
<div className="relative flex h-full flex-col justify-between p-6 sm:p-10">
<header className="flex items-center justify-between text-sm">
<a href="#" className="font-semibold tracking-tight">
Tinta
</a>
<nav className="flex gap-5 text-white/70 sm:gap-7">
<a href="#" className="transition-colors hover:text-white">
Work
</a>
<a href="#" className="hidden transition-colors hover:text-white sm:inline">
Studio
</a>
<a href="#" className="transition-colors hover:text-white">
Contact
</a>
</nav>
</header>
<div className="max-w-xl">
<p className="font-mono text-xs tracking-widest text-white/60 uppercase">
Brand & motion studio · Lisbon
</p>
<h1 className="mt-3 text-4xl font-semibold tracking-tight text-balance sm:text-6xl">
Color that stays with you.
</h1>
<p className="mt-4 max-w-sm text-pretty text-white/70">
Identities, campaigns and the motion between them, for brands that want to be remembered.
</p>
</div>
</div>
</PaintReveal>
);
}
Live preview, examples and props: https://keyframeui.com/components/paint-reveal#paint-reveal-demo




















