All Taste components
Gradient heroes
Lava lamp hero
A left-aligned opening section with warm and cool blobs that rise, sink and change shape on the right, like a lava lamp.
2-colour lava · shape-shifting blobs · left copy · listen CTA · meta row
Music for deep work
Slow music for fast work.
Ember plays long, quiet sets that fit the time you have to focus — no ads, no lyrics, no sudden drops.
import { Check, Play } from "lucide-react";
/* Each blob: an outer layer that rises or sinks, an inner layer with an uneven
radius that turns and stretches (transform only — the blur is set once).
Add once to globals.css:
@keyframes lava-morph { 0% { transform: rotate(0) scale(1, 1); } 33% { transform: rotate(120deg) scale(1.14, .88); } 66% { transform: rotate(240deg) scale(.9, 1.12); } 100% { transform: rotate(360deg) scale(1, 1); } }
@keyframes lava-sink { to { transform: translate(-12%, 72%); } }
@keyframes lava-rise { to { transform: translate(14%, -86%); } }
*/
const shape = "size-full rounded-[42%_58%_63%_37%/45%_39%_61%_55%] blur-[26px] animate-[lava-morph_16s_linear_infinite] motion-reduce:animate-none";
export function HeroLava() {
return (
<section aria-labelledby="lava-title" className="relative isolate overflow-hidden bg-bg px-5 pb-24 pt-5 font-sans text-fg sm:px-10">
<div aria-hidden className="absolute inset-0 -z-10 overflow-hidden bg-[linear-gradient(to_left,color-mix(in_srgb,var(--tst-warning)_7%,var(--tst-bg)),var(--tst-bg)_60%)] opacity-70 md:opacity-100">
<span className="absolute right-[8%] top-[4%] aspect-square w-[max(30%,230px)] animate-[lava-sink_19s_ease-in-out_infinite_alternate] motion-reduce:animate-none">
<span className={shape + " block bg-gradient-to-br from-warning to-danger opacity-70"} />
</span>
<span className="absolute -bottom-[6%] right-[24%] aspect-square w-[max(25%,200px)] animate-[lava-rise_23s_ease-in-out_infinite_alternate] motion-reduce:animate-none">
<span className={shape + " block bg-gradient-to-bl from-primary to-info opacity-65 [animation-direction:reverse] [animation-duration:20s]"} />
</span>
<span className="absolute bottom-[14%] right-[2%] aspect-square w-[max(11%,90px)] animate-[lava-rise_15s_ease-in-out_infinite_alternate-reverse] motion-reduce:animate-none">
<span className={shape + " block bg-gradient-to-br from-warning to-danger opacity-70 [animation-duration:12s]"} />
</span>
</div>
<nav aria-label="Main" className="mx-auto mb-16 flex max-w-[1080px] items-center justify-between gap-4 sm:mb-24">
<a href="/" className="flex items-center gap-2 text-[15px] font-semibold">
<span className="size-[22px] rounded-sm bg-gradient-to-br from-primary to-info" /> Ember
</a>
<a href="/signup" className="inline-flex h-8 items-center rounded bg-primary px-3 text-[13px] font-medium text-primary-fg hover:bg-primary-hover">Try Ember</a>
</nav>
<div className="mx-auto flex min-h-[360px] max-w-[1080px] flex-col items-start justify-center gap-5">
<span className="text-xs font-medium uppercase tracking-[.1em] text-fg-muted animate-rise motion-reduce:animate-none">Music for deep work</span>
<h1 id="lava-title" className="max-w-[11ch] text-balance text-4xl font-medium leading-[1.02] tracking-[-0.04em] sm:text-6xl lg:text-7xl animate-rise [animation-delay:80ms] motion-reduce:animate-none">
Slow music for fast work.
</h1>
<p className="max-w-[460px] text-pretty text-base leading-relaxed text-fg-muted sm:text-lg animate-rise [animation-delay:160ms] motion-reduce:animate-none">
Ember plays long, quiet sets that fit the time you have to focus — no ads, no lyrics, no sudden drops.
</p>
<div className="flex flex-wrap gap-2.5 animate-rise [animation-delay:240ms] motion-reduce:animate-none">
<a href="/session" className="inline-flex h-11 items-center rounded bg-primary px-5 font-medium text-primary-fg hover:bg-primary-hover active:scale-[.97]">Start a session</a>
<button type="button" className="inline-flex h-11 items-center gap-1.5 rounded border border-border-strong bg-bg px-5 font-medium hover:bg-surface active:scale-[.97]">
<Play className="size-4" aria-hidden /> Play a sample
</button>
</div>
<ul className="flex flex-wrap gap-x-5 gap-y-2 text-[13px] text-fg-muted">
{["52-minute average session", "Works offline"].map((t) => (
<li key={t} className="flex items-center gap-1.5"><Check className="size-3.5 text-primary" aria-hidden />{t}</li>
))}
</ul>
</div>
</section>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.