GRV-Summit-Site/components/brand/RiftPulseField.tsx
“kirukib” 3693495dd0
Some checks are pending
Deploy to Cloudflare Workers (OpenNext) / deploy (push) Waiting to run
Add site-wide topography patterns and refine section styling.
Use mainwhite.svg on white sections with curvy green transitions into flat green bands, improve text and button contrast, and deploy via OpenNext on Cloudflare Workers.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-20 20:34:36 +03:00

75 lines
2.4 KiB
TypeScript

"use client";
import { useMemo } from "react";
import { mixHex } from "@/lib/rift-colors";
import { cn } from "@/lib/utils";
const GREEN = "#1a5c38";
const GOLD = "#ffb300";
const BLUE = "#1f3d7e";
/** Long curved paths that pulse across the page background */
const PULSE_CURVES = [
"M -80 120 Q 280 80, 520 140 T 1040 100 T 1400 160",
"M -60 280 Q 320 240, 580 300 T 1100 260 T 1500 320",
"M -100 440 Q 260 400, 500 460 T 980 420 T 1380 480",
"M -40 600 Q 300 560, 620 620 T 1080 580 T 1520 640",
"M -120 180 Q 200 220, 480 160 T 920 200 T 1320 140",
"M -80 520 Q 340 480, 640 540 T 1020 500 T 1480 560",
"M -60 720 Q 400 680, 720 740 T 1140 700 T 1600 760",
"M -100 860 Q 280 820, 560 880 T 1000 840 T 1440 900",
] as const;
type Props = {
progress: number;
scrollY: number;
reduceMotion: boolean;
};
export function RiftPulseField({ progress, scrollY, reduceMotion }: Props) {
const t = Math.max(0, Math.min(1, progress));
const wave = 0.5 - 0.5 * Math.cos(t * Math.PI * 2);
const primary = useMemo(() => {
if (t < 0.33) return mixHex(GREEN, GOLD, t / 0.33);
if (t < 0.66) return mixHex(GOLD, BLUE, (t - 0.33) / 0.33);
return mixHex(BLUE, GREEN, (t - 0.66) / 0.34);
}, [t]);
const accent = useMemo(() => mixHex(GOLD, primary, 0.35 + wave * 0.2), [primary, wave]);
const yShift = reduceMotion ? 0 : scrollY * 0.04;
const drawOffset = reduceMotion ? 0 : Math.max(0, 0.92 - progress * 1.1);
return (
<svg
className="rift-pulse-field pointer-events-none absolute inset-0 h-full w-full"
viewBox="0 0 1280 1000"
preserveAspectRatio="xMidYMid slice"
aria-hidden
style={{
transform: `translate3d(0, ${yShift}px, 0)`,
opacity: 0.35 + progress * 0.4,
}}
>
<g fill="none" strokeLinecap="round">
{PULSE_CURVES.map((d, i) => (
<path
key={i}
pathLength={1}
d={d}
stroke={i % 2 === 0 ? primary : accent}
strokeWidth={0.8 + (i % 3) * 0.2}
className={cn("rift-pulse-line", !reduceMotion && "rift-pulse-animate")}
style={{
animationDelay: `${i * 0.55}s`,
strokeDasharray: 1,
strokeDashoffset: drawOffset,
transition: "stroke 0.85s ease, stroke-dashoffset 0.3s ease-out",
}}
/>
))}
</g>
</svg>
);
}