All Taste components
Animated heroes
Hero with floating cards
An opening section whose headline arrives word by word while product cards drift beside it.
word-by-word headline · rising buttons · 3 floating cards · stacks on narrow widths
NewAuto-match for bank feeds
Closeyourbooksbeforethecoffeegetscold.
Northwind matches every payment to its invoice the moment it lands, so month-end is a review, not a rescue.
14-day trial · No card needed
import { ArrowRight, Check } from "lucide-react";
/* Add once to globals.css (the Taste preset already has rise, fade, pop, float, grow-*):
@keyframes word-in { from { opacity: 0; transform: translateY(.45em); filter: blur(8px); } }
@keyframes card-in { from { opacity: 0; transform: translateY(28px) scale(.94); } }
*/
const hero = {
pill: { tag: "New", label: "Auto-match for bank feeds", href: "/changelog" },
title: "Close your books before the coffee gets cold.",
lead: "Northwind matches every payment to its invoice the moment it lands, so month-end is a review, not a rescue.",
note: "14-day trial · No card needed",
};
const cashBars = [38, 52, 44, 63, 57, 72, 66, 88];
export function HeroFloatingCards() {
const words = hero.title.split(" ");
return (
<section aria-labelledby="hero-title" className="overflow-hidden bg-bg font-sans">
<div className="mx-auto grid max-w-6xl items-center gap-12 px-4 py-20 sm:px-6 lg:grid-cols-[1.05fr_1fr]">
<div className="flex flex-col items-start gap-5">
<a href={hero.pill.href} className="inline-flex items-center gap-2 rounded-full border border-border bg-bg py-0.5 pl-0.5 pr-3 text-[13px] text-fg-muted animate-fade motion-reduce:animate-none">
<span className="rounded-full bg-primary-soft px-2 py-0.5 text-xs font-medium text-primary-soft-fg">{hero.pill.tag}</span>
{hero.pill.label}
<ArrowRight className="size-3.5" aria-hidden />
</a>
<h1 id="hero-title" className="text-balance text-4xl font-medium leading-[1.05] tracking-tight text-fg sm:text-5xl">
{words.map((w, i) => (
<span
key={i}
className="mr-[.24em] inline-block animate-[word-in_.8s_cubic-bezier(.2,.7,.1,1)_both] motion-reduce:animate-none"
style={{ animationDelay: 120 + i * 65 + "ms" }}
>
{w}
</span>
))}
</h1>
<p className="max-w-lg text-pretty text-base leading-relaxed text-fg-muted animate-rise [animation-delay:520ms] motion-reduce:animate-none">{hero.lead}</p>
<div className="flex flex-wrap gap-3">
<a href="/signup" className="inline-flex h-11 items-center gap-1.5 rounded bg-primary px-5 font-medium text-primary-fg transition hover:bg-primary-hover active:scale-[.97] animate-pop [animation-delay:720ms] motion-reduce:animate-none">
Start free <ArrowRight className="size-4" aria-hidden />
</a>
<a href="/demo" className="inline-flex h-11 items-center rounded border border-border-strong bg-bg px-5 font-medium text-fg transition hover:bg-surface animate-pop [animation-delay:800ms] motion-reduce:animate-none">
Book a demo
</a>
</div>
<p className="text-[13px] text-fg-subtle animate-fade [animation-delay:900ms] motion-reduce:animate-none">{hero.note}</p>
</div>
{/* Product cards: each one springs in, then floats on its own phase */}
<div aria-hidden className="relative h-[300px]">
<div className="absolute inset-y-[6%] inset-x-0 rounded-full bg-[radial-gradient(closest-side,color-mix(in_srgb,var(--tst-primary)_22%,transparent),transparent)]" />
<FloatingCard className="left-0 top-0 w-[min(250px,78%)]" index={0} tilt="-rotate-2">
<div className="flex items-center gap-2.5">
<span className="grid size-8 place-items-center rounded bg-success-soft text-success-fg"><Check className="size-4" /></span>
<div>
<div className="text-lg font-medium tabular-nums tracking-tight text-fg">+₹48,200</div>
<div className="text-xs text-fg-muted">Kestrel Studio · just now</div>
</div>
</div>
</FloatingCard>
<FloatingCard className="right-0 top-[30%] w-[min(232px,72%)]" index={1} tilt="rotate-[1.5deg]">
<div className="flex justify-between text-xs text-fg-subtle"><span>Cash in, 30 days</span><span className="text-success-fg">+18%</span></div>
<div className="mt-1 text-lg font-medium tabular-nums text-fg">₹6,42,800</div>
<div className="mt-2 flex h-14 items-end gap-1">
{cashBars.map((h, i) => (
<span
key={i}
className={"flex-1 origin-bottom rounded-t-sm animate-grow-y motion-reduce:animate-none " + (i === cashBars.length - 1 ? "bg-primary" : "bg-primary-soft")}
style={{ height: h + "%", animationDelay: 900 + i * 55 + "ms" }}
/>
))}
</div>
</FloatingCard>
<FloatingCard className="bottom-0 left-[6%] w-[min(226px,70%)]" index={2} tilt="-rotate-1">
<p className="text-sm text-fg-muted">3 reminders sent</p>
<div className="mt-2 h-1.5 overflow-hidden rounded-full bg-surface-2">
<span className="block h-full w-[72%] origin-left rounded-full bg-primary animate-grow-x [animation-delay:1100ms] motion-reduce:animate-none" />
</div>
</FloatingCard>
</div>
</div>
</section>
);
}
function FloatingCard({ className, index, tilt, children }: { className: string; index: number; tilt: string; children: React.ReactNode }) {
return (
<div
className={"absolute animate-[card-in_.9s_cubic-bezier(.34,1.56,.64,1)_both] motion-reduce:animate-none " + className}
style={{ animationDelay: 520 + index * 150 + "ms" }}
>
<div className={tilt}>
<div
className="rounded-lg border border-border bg-bg p-3.5 shadow-[0_18px_40px_-26px_rgb(0_0_0/.35)] animate-float motion-reduce:animate-none"
style={{ animationDelay: index * -1.9 + "s", animationDuration: "6s" }}
>
{children}
</div>
</div>
</div>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.