All Taste components
Gradient heroes
App icon halo hero
An app launch section with the app icon at its centre, ringed by a turning, breathing halo of colour.
rotating colour ring · pulsing glow · app icon · download buttons · rating
Plan the week’s meals before you’re hungry.
Pantry builds a shopping list from the recipes you pick and what is already in your fridge, so less ends up in the bin.
import { Leaf, Smartphone, Star } from "lucide-react";
/* The ring is a conic gradient cut to a band with a radial mask, blurred once,
then turned; its wrapper breathes.
Add once to globals.css:
@keyframes halo-spin { to { transform: rotate(1turn); } }
@keyframes halo-pulse { from { transform: scale(.92); opacity: .7; } to { transform: scale(1.06); opacity: 1; } }
@keyframes drift-a { to { transform: translate(18%, 22%) scale(1.12); } }
@keyframes drift-b { to { transform: translate(-22%, 18%) scale(.9); } }
*/
const ringMask = "radial-gradient(closest-side, transparent 58%, var(--tst-fg) 66%, var(--tst-fg) 76%, transparent 86%)";
export function HeroHalo() {
return (
<section aria-labelledby="halo-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-[radial-gradient(60%_50%_at_50%_30%,color-mix(in_srgb,var(--tst-primary)_8%,var(--tst-bg)),var(--tst-bg))]">
<span className="absolute -bottom-[40%] -left-[8%] aspect-square w-[max(40%,300px)] rounded-full bg-[radial-gradient(closest-side,color-mix(in_srgb,var(--tst-info)_30%,transparent),transparent)] animate-[drift-a_24s_ease-in-out_infinite_alternate] motion-reduce:animate-none" />
<span className="absolute -bottom-[36%] -right-[10%] aspect-square w-[max(40%,300px)] rounded-full bg-[radial-gradient(closest-side,color-mix(in_srgb,var(--tst-warning)_28%,transparent),transparent)] animate-[drift-b_28s_ease-in-out_infinite_alternate] motion-reduce:animate-none" />
</div>
<nav aria-label="Main" className="mx-auto mb-12 flex max-w-[1080px] items-center justify-between gap-4 sm:mb-16">
<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" /> Pantry
</a>
<a href="/download" className="inline-flex h-8 items-center rounded bg-primary px-3 text-[13px] font-medium text-primary-fg hover:bg-primary-hover">Get the app</a>
</nav>
<div className="mx-auto flex max-w-[1080px] flex-col items-center gap-5 text-center">
<div className="relative -mb-9 -mt-6 grid size-60 place-items-center animate-rise motion-reduce:animate-none">
<span aria-hidden className="absolute -inset-[30%] rounded-full bg-[radial-gradient(closest-side,color-mix(in_srgb,var(--tst-primary)_40%,transparent),transparent)] animate-[halo-pulse_6s_ease-in-out_infinite_alternate] motion-reduce:animate-none" />
<span aria-hidden className="absolute inset-0 animate-[halo-pulse_6s_ease-in-out_infinite_alternate] motion-reduce:animate-none">
<span className="absolute inset-0 rounded-full bg-[conic-gradient(var(--tst-primary),var(--tst-info),var(--tst-success),var(--tst-warning),var(--tst-danger),var(--tst-primary))] blur-[10px] will-change-transform animate-[halo-spin_18s_linear_infinite] motion-reduce:animate-none"
style={{ maskImage: ringMask, WebkitMaskImage: ringMask }} />
</span>
<span role="img" aria-label="Pantry app icon" className="relative grid size-24 place-items-center rounded-[calc(var(--tst-radius-xl)*1.4)] bg-gradient-to-br from-primary to-[color-mix(in_srgb,var(--tst-primary)_55%,var(--tst-info))] text-primary-fg shadow-[0_20px_40px_-16px_color-mix(in_srgb,var(--tst-primary)_70%,transparent)]">
<Leaf className="size-11" aria-hidden />
</span>
</div>
<h1 id="halo-title" className="max-w-[13ch] 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">
Plan the week’s meals before you’re hungry.
</h1>
<p className="max-w-xl text-pretty text-base leading-relaxed text-fg-muted sm:text-lg animate-rise [animation-delay:160ms] motion-reduce:animate-none">
Pantry builds a shopping list from the recipes you pick and what is already in your fridge, so less ends up in the bin.
</p>
<div className="flex flex-wrap justify-center gap-2.5 animate-rise [animation-delay:240ms] motion-reduce:animate-none">
<a href="/ios" className="inline-flex h-11 items-center gap-1.5 rounded bg-primary px-5 font-medium text-primary-fg hover:bg-primary-hover active:scale-[.97]">
<Smartphone className="size-4" aria-hidden /> Download for iPhone
</a>
<a href="/android" 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]">
<Smartphone className="size-4" aria-hidden /> Get it on Android
</a>
</div>
<p className="inline-flex items-center gap-2 text-[13px] text-fg-muted">
<span className="inline-flex gap-0.5 text-warning" aria-label="Rated 4.8 out of 5">
{[0, 1, 2, 3, 4].map((i) => <Star key={i} className="size-3.5 fill-current" aria-hidden />)}
</span>
4.8 · 12,400 ratings
</p>
</div>
</section>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.