Components
Loading preview...
@aayush-duhan
npx shadcn@latest add https://21st.dev/r/aayush-duhan/liquid-gradient"use client";
import { useMemo, useState } from "react";
import {
LiquidGradientCanvas,
LIQUID_GRADIENT_PRESETS,
type LiquidGradientPresetName,
} from "@/components/ui/liquid-gradient";
const PRESETS: { key: LiquidGradientPresetName; label: string }[] = [
{ key: "sunset", label: "Sunset" },
{ key: "aurora", label: "Aurora" },
{ key: "vibrant", label: "Vibrant" },
{ key: "magma", label: "Magma" },
{ key: "subtleDark", label: "Subtle" },
];
export default function LiquidGradientDemo() {
const [preset, setPreset] = useState<LiquidGradientPresetName>("sunset");
const [speed, setSpeed] = useState(0.6);
const [paused, setPaused] = useState(false);
const params = useMemo(() => LIQUID_GRADIENT_PRESETS[preset], [preset]);
return (
<div className="flex min-h-[600px] w-full items-center justify-center p-4 sm:p-8">
<div className="relative h-[540px] w-full max-w-3xl overflow-hidden rounded-3xl border border-white/10 shadow-2xl">
<LiquidGradientCanvas
{...params}
speed={speed}
paused={paused}
className="absolute inset-0 h-full w-full"
/>
<div className="relative flex h-full flex-col justify-between p-6 sm:p-8">
<div className="flex justify-end">
<button
type="button"
onClick={() => setPaused((p) => !p)}
className="rounded-full border border-white/20 bg-white/10 px-4 py-1.5 text-xs font-medium text-white backdrop-blur-md transition-colors hover:bg-white/20"
>
{paused ? "Play" : "Pause"}
</button>
</div>
<div className="flex flex-col gap-4">
<div className="flex flex-wrap gap-2">
{PRESETS.map(({ key, label }) => (
<button
key={key}
type="button"
onClick={() => setPreset(key)}
className={`rounded-full border px-3 py-1.5 text-xs font-medium backdrop-blur-md transition-colors ${
preset === key
? "border-white/60 bg-white/25 text-white"
: "border-white/15 bg-white/5 text-white/70 hover:bg-white/15"
}`}
>
{label}
</button>
))}
</div>
<label className="flex items-center gap-3 text-xs font-medium text-white/80">
<span className="w-12 shrink-0">Speed</span>
<input
type="range"
min={0}
max={2}
step={0.05}
value={speed}
onChange={(e) => setSpeed(parseFloat(e.target.value))}
className="h-1 flex-1 cursor-pointer appearance-none rounded-full bg-white/20 accent-white"
aria-label="Animation speed"
/>
<span className="w-10 shrink-0 text-right font-mono tabular-nums">
{speed.toFixed(2)}
</span>
</label>
</div>
</div>
</div>
</div>
);
}