proNew306 lines · framer-motion
Hero Shader Waves
Raw WebGL waves, breathing behind the pitch. A full-width launch hero backed by a hand-written WebGL fragment shader: layered sine wave bands sweep across the frame and blend between two theme colours.
- Use it for
- The first screen of an AI product or SaaS launch page that wants a shader backdrop without pulling in a 3D engine.
- Themes
- Light + dark
- License
- Commercial use
Live
Signal · Launch week
Waves of signal, not noise
A shader-driven hero backdrop that breathes behind your pitch, tuned for AI product launches.
tsx
"use client";
import * as React from "react";
import { motion, useReducedMotion } from "framer-motion";
import { cn } from "@/lib/utils";
function useReducedMotionSafe() {
const prefersReduced = useReducedMotion();
const [mounted, setMounted] = React.useState(false);
React.useEffect(() => setMounted(true), []);
return mounted ? !!prefersReduced : false;
}
/**
* Full-bleed landing hero whose backdrop is a raw WebGL fragment shader: layered
* sine wave bands sweep left to right and blend between two theme colours. Falls
* back to a static CSS gradient when WebGL is unavailable.
*/
export interface HeroShaderWavesProps {
eyebrow?: string;
headline?: string;The rest is in Pro.
Full source, the rebuild prompt and registry install unlock with Pro or Lifetime.
Get ProHow it behaves
- →A single WebGL1 context draws a full-screen triangle strip; the fragment shader layers up to 6 sine wave bands (waveCount) that sweep horizontally at uSpeed and blend between two theme colours plus an accent.
- →Colours are read from the design tokens (--signal/--info/--lime/--foreground depending on palette) at mount and re-read from computed styles whenever the <html> class attribute changes (MutationObserver), so the shader snaps to the new theme instantly.
- →If canvas.getContext("webgl") returns null, the component swaps to a static CSS linear-gradient backdrop instead of throwing.
- →Canvas is resized to the host element at a capped device pixel ratio (max 2) via ResizeObserver; the render loop pauses when the hero scrolls offscreen (IntersectionObserver) or the tab is hidden.
- →On unmount: cancels the frame, disconnects observers, deletes the buffer/program/shaders and calls the WEBGL_lose_context extension so the context is actually released.
- →prefers-reduced-motion renders one still frame instead of looping.
Accessibility
- ✓Canvas and gradient fallback are aria-hidden; only the eyebrow, heading, copy and two real <a> CTAs are in the accessibility tree.
- ✓Headline is a single <h1>; CTAs keep the design system's visible focus ring.
- ✓A background/background gradient scrim sits under the text column so contrast stays high over the shader in both themes.
- ✓Honours prefers-reduced-motion.