Initial commit
This commit is contained in:
44
src/components/background/AnimatedAuroraBackground.tsx
Normal file
44
src/components/background/AnimatedAuroraBackground.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
"use client";
|
||||
import React, { memo } from "react";
|
||||
import { cls } from "@/lib/utils";
|
||||
|
||||
interface AnimatedAuroraBackgroundProps {
|
||||
className?: string;
|
||||
showRadialGradient?: boolean;
|
||||
/**
|
||||
* Inverts the aurora colors for better visibility.
|
||||
* Use `true` for light backgrounds (makes aurora darker/inverted)
|
||||
* Use `false` for dark backgrounds (keeps aurora colors vibrant)
|
||||
*/
|
||||
invertColors: boolean;
|
||||
}
|
||||
|
||||
const AnimatedAuroraBackground = ({
|
||||
className,
|
||||
showRadialGradient = true,
|
||||
invertColors,
|
||||
}: AnimatedAuroraBackgroundProps) => {
|
||||
return (
|
||||
<div
|
||||
className={cls(
|
||||
"fixed inset-0 -z-10 bg-background",
|
||||
className
|
||||
)}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div className="absolute inset-0 overflow-hidden opacity-30">
|
||||
<div
|
||||
className={cls(
|
||||
"[--base-gradient:repeating-linear-gradient(100deg,var(--background)_0%,var(--background)_7%,transparent_10%,transparent_12%,var(--background)_16%)] [--aurora:repeating-linear-gradient(100deg,var(--color-primary-cta)_10%,var(--color-accent)_15%,var(--color-secondary-cta)_20%,var(--color-accent)_25%,var(--color-primary-cta)_30%)] [background-image:var(--base-gradient),var(--aurora)] [background-size:300%,_200%] [background-position:50%_50%,50%_50%] filter blur-[10px] after:content-[''] after:absolute after:inset-0 after:[background-image:var(--base-gradient),var(--aurora)] after:[background-size:200%,_100%] after:[animation:aurora_60s_linear_infinite] after:[background-attachment:fixed] after:mix-blend-difference pointer-events-none absolute -inset-[10px] opacity-30 will-change-transform",
|
||||
invertColors && "invert",
|
||||
showRadialGradient && "[mask-image:radial-gradient(ellipse_at_100%_0%,black_10%,var(--transparent)_70%)]"
|
||||
)}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
AnimatedAuroraBackground.displayName = "AnimatedAuroraBackground";
|
||||
|
||||
export default memo(AnimatedAuroraBackground);
|
||||
111
src/components/background/AnimatedGridBackground.tsx
Normal file
111
src/components/background/AnimatedGridBackground.tsx
Normal file
@@ -0,0 +1,111 @@
|
||||
"use client";
|
||||
|
||||
import { memo, useEffect, useId, useRef, useState } from "react";
|
||||
import { motion } from "framer-motion";
|
||||
import { cls } from "@/lib/utils";
|
||||
|
||||
interface AnimatedGridBackgroundProps {
|
||||
className?: string;
|
||||
squareSize?: number;
|
||||
numSquares?: number;
|
||||
maxOpacity?: number;
|
||||
perspectiveThreeD?: boolean;
|
||||
}
|
||||
|
||||
const AnimatedGridBackground = ({
|
||||
className = "",
|
||||
squareSize = 100,
|
||||
numSquares = 50,
|
||||
maxOpacity = 0.15,
|
||||
perspectiveThreeD = true,
|
||||
}: AnimatedGridBackgroundProps) => {
|
||||
const id = useId();
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [dimensions, setDimensions] = useState({ width: 0, height: 0 });
|
||||
const [squares, setSquares] = useState<Array<{ id: number; pos: [number, number] }>>([]);
|
||||
|
||||
useEffect(() => {
|
||||
if (containerRef.current) {
|
||||
const { width, height } = containerRef.current.getBoundingClientRect();
|
||||
setDimensions({ width, height });
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (dimensions.width && dimensions.height) {
|
||||
const cols = Math.ceil(dimensions.width / squareSize);
|
||||
const rows = Math.ceil(dimensions.height / squareSize);
|
||||
|
||||
const newSquares = Array.from({ length: numSquares }, (_, i) => ({
|
||||
id: i,
|
||||
pos: [
|
||||
Math.floor(Math.random() * cols),
|
||||
Math.floor(Math.random() * rows),
|
||||
] as [number, number],
|
||||
}));
|
||||
|
||||
setSquares(newSquares);
|
||||
}
|
||||
}, [dimensions, squareSize, numSquares]);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={cls(
|
||||
"fixed inset-0 -z-10 overflow-hidden [mask-image:radial-gradient(circle_at_center,white_0%,transparent_90%)]",
|
||||
perspectiveThreeD && "inset-x-0 inset-y-[-30%] h-[200%] skew-y-12",
|
||||
className
|
||||
)}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<svg
|
||||
width="100%"
|
||||
height="100%"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<defs>
|
||||
<pattern
|
||||
id={`grid-${id}`}
|
||||
width={squareSize}
|
||||
height={squareSize}
|
||||
patternUnits="userSpaceOnUse"
|
||||
>
|
||||
<path
|
||||
d={`M ${squareSize} 0 L 0 0 0 ${squareSize}`}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1"
|
||||
className="text-accent/20"
|
||||
/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill={`url(#grid-${id})`} />
|
||||
{squares.map(({ id, pos: [x, y] }) => (
|
||||
<motion.rect
|
||||
key={id}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{
|
||||
opacity: [0, maxOpacity, 0],
|
||||
}}
|
||||
transition={{
|
||||
duration: Math.random() * 2 + 2,
|
||||
repeat: Infinity,
|
||||
delay: Math.random() * 2,
|
||||
ease: "easeInOut",
|
||||
}}
|
||||
x={x * squareSize}
|
||||
y={y * squareSize}
|
||||
width={squareSize}
|
||||
height={squareSize}
|
||||
fill="var(--color-background-accent)"
|
||||
strokeWidth="0"
|
||||
/>
|
||||
))}
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
AnimatedGridBackground.displayName = "AnimatedGridBackground";
|
||||
|
||||
export default memo(AnimatedGridBackground);
|
||||
32
src/components/background/AuroraBackground.tsx
Normal file
32
src/components/background/AuroraBackground.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
"use client";
|
||||
|
||||
import { memo } from "react";
|
||||
import { cls } from "@/lib/utils";
|
||||
|
||||
interface AuroraBackgroundProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const AuroraBackground = ({
|
||||
className = "",
|
||||
}: AuroraBackgroundProps) => {
|
||||
return (
|
||||
<div className={cls("fixed inset-0 z-0 w-full h-full bg-background", className)}>
|
||||
<div className="absolute top-0 left-0 w-full h-full z-10 backdrop-blur-3xl" ></div>
|
||||
{/* top center */}
|
||||
<div className="absolute top-0 left-1/2 -translate-y-1/2 -translate-x-[120%] w-[9vw] h-[110vh] bg-background-accent/10 -rotate-[52.5deg] rounded-[100%]" />
|
||||
{/* top right */}
|
||||
<div className="absolute top-[-20vh] right-[2.5vw] -translate-x-[0%] w-[12.5vw] h-[100vh] bg-background-accent/10 -rotate-[60deg] rounded-[100%]" />
|
||||
{/* center left */}
|
||||
<div className="absolute top-[-20vh] left-[2vw] -translate-x-[0%] w-[15vw] h-[150vh] bg-background-accent/10 -rotate-[45deg] rounded-[100%]" />
|
||||
{/* top left */}
|
||||
<div className="absolute top-[-30vh] left-0 -translate-x-[0%] w-[10vw] h-[70vh] bg-background-accent/10 -rotate-[45deg] rounded-[100%]" />
|
||||
{/* bottom center */}
|
||||
<div className="absolute bottom-[-40vh] left-0 -translate-x-[0%] w-[120vw] h-[50vh] bg-background-accent/5 -rotate-[20deg] rounded-[100%]" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
AuroraBackground.displayName = "AuroraBackground";
|
||||
|
||||
export default memo(AuroraBackground);
|
||||
58
src/components/background/BlurBottomBackground.tsx
Normal file
58
src/components/background/BlurBottomBackground.tsx
Normal file
@@ -0,0 +1,58 @@
|
||||
"use client";
|
||||
|
||||
import { memo, useState, useEffect, useCallback } from "react";
|
||||
import { cls } from "@/lib/utils";
|
||||
|
||||
const MASK_GRADIENT = "linear-gradient(to bottom, transparent, black 60%)";
|
||||
const BOTTOM_THRESHOLD = 50;
|
||||
const TOP_THRESHOLD = 50;
|
||||
|
||||
interface BlurBottomBackgroundProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const BlurBottomBackground = ({
|
||||
className = ""
|
||||
}: BlurBottomBackgroundProps) => {
|
||||
const [isAtBottom, setIsAtBottom] = useState(false);
|
||||
const [isAtTop, setIsAtTop] = useState(true);
|
||||
|
||||
const handleScroll = useCallback(() => {
|
||||
const scrollTop = window.scrollY || document.documentElement.scrollTop;
|
||||
const windowHeight = window.innerHeight;
|
||||
const documentHeight = document.documentElement.scrollHeight;
|
||||
|
||||
const distanceFromBottom = documentHeight - (scrollTop + windowHeight);
|
||||
|
||||
setIsAtTop(scrollTop <= TOP_THRESHOLD);
|
||||
setIsAtBottom(distanceFromBottom <= BOTTOM_THRESHOLD);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
handleScroll();
|
||||
|
||||
window.addEventListener("scroll", handleScroll, { passive: true });
|
||||
window.addEventListener("resize", handleScroll, { passive: true });
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("scroll", handleScroll);
|
||||
window.removeEventListener("resize", handleScroll);
|
||||
};
|
||||
}, [handleScroll]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cls(
|
||||
"fixed pointer-events-none backdrop-blur-xl w-full h-50 left-0 bottom-0 z-[500] transition-opacity duration-500 ease-out",
|
||||
isAtTop || isAtBottom ? "opacity-0" : "opacity-100",
|
||||
className
|
||||
)}
|
||||
style={{ maskImage: MASK_GRADIENT }}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
BlurBottomBackground.displayName = "BlurBottomBackground";
|
||||
|
||||
export default memo(BlurBottomBackground);
|
||||
48
src/components/background/CircleGradientBackground.tsx
Normal file
48
src/components/background/CircleGradientBackground.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
"use client";
|
||||
|
||||
import { memo } from "react";
|
||||
import { cls } from "@/lib/utils";
|
||||
|
||||
type DiagonalVariant = "primary" | "secondary";
|
||||
|
||||
interface CircleGradientBackgroundProps {
|
||||
className?: string;
|
||||
diagonal?: DiagonalVariant;
|
||||
}
|
||||
|
||||
const CircleGradientBackground = ({
|
||||
className = "",
|
||||
diagonal = "primary",
|
||||
}: CircleGradientBackgroundProps) => {
|
||||
const isPrimary = diagonal === "primary";
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cls("fixed top-0 left-0 right-0 bottom-0 h-screen w-full -z-10 overflow-hidden", className)}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div
|
||||
className={cls(
|
||||
"fixed w-100 md:w-70 h-auto aspect-square rounded-full opacity-10",
|
||||
isPrimary ? "top-0 right-0 translate-x-1/2 -translate-y-1/2" : "top-0 left-0 -translate-x-1/2 -translate-y-1/2"
|
||||
)}
|
||||
style={{
|
||||
background: `radial-gradient(circle at center, var(--color-background-accent) 0%, transparent 70%)`,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className={cls(
|
||||
"fixed w-100 md:w-70 h-auto aspect-square rounded-full opacity-10",
|
||||
isPrimary ? "bottom-0 left-0 -translate-x-1/2 translate-y-1/2" : "bottom-0 right-0 translate-x-1/2 translate-y-1/2"
|
||||
)}
|
||||
style={{
|
||||
background: `radial-gradient(circle at center, var(--color-background-accent) 0%, transparent 70%)`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
CircleGradientBackground.displayName = "CircleGradientBackground";
|
||||
|
||||
export default memo(CircleGradientBackground);
|
||||
45
src/components/background/DotGridBackground.tsx
Normal file
45
src/components/background/DotGridBackground.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
"use client";
|
||||
|
||||
import { memo } from "react";
|
||||
import { cls } from "@/lib/utils";
|
||||
|
||||
type GridSize = "small" | "medium" | "large";
|
||||
|
||||
interface DotGridBackgroundProps {
|
||||
size?: GridSize;
|
||||
className?: string;
|
||||
perspectiveThreeD?: boolean;
|
||||
}
|
||||
|
||||
const GRID_SIZES: Record<GridSize, string> = {
|
||||
small: "1vw 1vw",
|
||||
medium: "2vw 2vw",
|
||||
large: "4vw 4vw",
|
||||
};
|
||||
|
||||
const DotGridBackground = ({
|
||||
size = "medium",
|
||||
className = "",
|
||||
perspectiveThreeD = false
|
||||
}: DotGridBackgroundProps) => {
|
||||
return (
|
||||
<div
|
||||
className={cls(
|
||||
"fixed inset-0 -z-10 bg-background [mask-image:radial-gradient(circle_at_center,white_0%,transparent_90%)]",
|
||||
perspectiveThreeD && "inset-x-0 inset-y-[-30%] h-[200%] skew-y-12",
|
||||
className
|
||||
)}
|
||||
style={{
|
||||
backgroundImage:
|
||||
"radial-gradient(circle, color-mix(in srgb, var(--background-accent) 30%, transparent) 1px, transparent 1px)",
|
||||
backgroundSize: GRID_SIZES[size],
|
||||
backgroundRepeat: "repeat",
|
||||
}}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
DotGridBackground.displayName = "DotGridBackground";
|
||||
|
||||
export default memo(DotGridBackground);
|
||||
277
src/components/background/FluidBackground.tsx
Normal file
277
src/components/background/FluidBackground.tsx
Normal file
@@ -0,0 +1,277 @@
|
||||
'use client';
|
||||
|
||||
import React, { useRef, useMemo, memo, useEffect, useState } from 'react';
|
||||
import { Canvas, useFrame, extend, useThree } from '@react-three/fiber';
|
||||
import { shaderMaterial } from '@react-three/drei';
|
||||
import * as THREE from 'three';
|
||||
import { cls } from '@/lib/utils';
|
||||
|
||||
const getComputedColor = (varName: string): THREE.Color => {
|
||||
if (typeof window === 'undefined') return new THREE.Color(0x000000);
|
||||
const styles = getComputedStyle(document.documentElement);
|
||||
const colorString = styles.getPropertyValue(varName).trim();
|
||||
return new THREE.Color(colorString || '#000000');
|
||||
};
|
||||
|
||||
const vertexShader = `
|
||||
varying vec2 vUv;
|
||||
void main() {
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const fragmentShader = `
|
||||
#ifdef GL_ES
|
||||
precision lowp float;
|
||||
#endif
|
||||
uniform float iTime;
|
||||
uniform vec2 iResolution;
|
||||
uniform vec3 uBackgroundColor;
|
||||
uniform vec3 uPrimaryCta;
|
||||
uniform vec3 uAccent;
|
||||
uniform vec3 uSecondaryCta;
|
||||
varying vec2 vUv;
|
||||
|
||||
vec4 buf[8];
|
||||
|
||||
vec4 sigmoid(vec4 x) { return 1. / (1. + exp(-x)); }
|
||||
|
||||
vec4 cppn_fn(vec2 coordinate, float in0, float in1, float in2) {
|
||||
buf[6] = vec4(coordinate.x, coordinate.y, 0.3948333106474662 + in0, 0.36 + in1);
|
||||
buf[7] = vec4(0.14 + in2, sqrt(coordinate.x * coordinate.x + coordinate.y * coordinate.y), 0., 0.);
|
||||
|
||||
buf[0] = mat4(vec4(6.5404263, -3.6126034, 0.7590882, -1.13613), vec4(2.4582713, 3.1660357, 1.2219609, 0.06276096), vec4(-5.478085, -6.159632, 1.8701609, -4.7742867), vec4(6.039214, -5.542865, -0.90925294, 3.251348))
|
||||
* buf[6]
|
||||
+ mat4(vec4(0.8473259, -5.722911, 3.975766, 1.6522468), vec4(-0.24321538, 0.5839259, -1.7661959, -5.350116), vec4(0.0, 0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0))
|
||||
* buf[7]
|
||||
+ vec4(0.21808943, 1.1243913, -1.7969975, 5.0294676);
|
||||
|
||||
buf[1] = mat4(vec4(-3.3522482, -6.0612736, 0.55641043, -4.4719114), vec4(0.8631464, 1.7432913, 5.643898, 1.6106541), vec4(2.4941394, -3.5012043, 1.7184316, 6.357333), vec4(3.310376, 8.209261, 1.1355612, -1.165539))
|
||||
* buf[6]
|
||||
+ mat4(vec4(5.24046, -13.034365, 0.009859298, 15.870829), vec4(2.987511, 3.129433, -0.89023495, -1.6822904), vec4(0.0, 0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0))
|
||||
* buf[7]
|
||||
+ vec4(-5.9457836, -6.573602, -0.8812491, 1.5436668);
|
||||
|
||||
buf[0] = sigmoid(buf[0]);
|
||||
buf[1] = sigmoid(buf[1]);
|
||||
|
||||
buf[2] = mat4(vec4(-15.219568, 8.095543, -2.429353, -1.9381982), vec4(-5.951362, 4.3115187, 2.6393783, 1.274315), vec4(-7.3145227, 6.7297835, 5.2473326, 5.9411426), vec4(5.0796127, 8.979051, -1.7278991, -1.158976))
|
||||
* buf[6]
|
||||
+ mat4(vec4(-11.967154, -11.608155, 6.1486754, 11.237008), vec4(2.124141, -6.263192, -1.7050359, -0.7021966), vec4(0.0, 0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0))
|
||||
* buf[7]
|
||||
+ vec4(-4.17164, -3.2281182, -4.576417, -3.6401186);
|
||||
|
||||
buf[3] = mat4(vec4(3.1832156, -13.738922, 1.879223, 3.233465), vec4(0.64300746, 12.768129, 1.9141049, 0.50990224), vec4(-0.049295485, 4.4807224, 1.4733979, 1.801449), vec4(5.0039253, 13.000481, 3.3991797, -4.5561905))
|
||||
* buf[6]
|
||||
+ mat4(vec4(-0.1285731, 7.720628, -3.1425676, 4.742367), vec4(0.6393625, 3.714393, -0.8108378, -0.39174938), vec4(0.0, 0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0))
|
||||
* buf[7]
|
||||
+ vec4(-1.1811101, -21.621881, 0.7851888, 1.2329718);
|
||||
|
||||
buf[2] = sigmoid(buf[2]);
|
||||
buf[3] = sigmoid(buf[3]);
|
||||
|
||||
buf[4] = mat4(vec4(5.214916, -7.183024, 2.7228765, 2.6592617), vec4(-5.601878, -25.3591, 4.067988, 0.4602802), vec4(-10.57759, 24.286327, 21.102104, 37.546658), vec4(4.3024497, -1.9625226, 2.3458803, -1.372816))
|
||||
* buf[0]
|
||||
+ mat4(vec4(-17.6526, -10.507558, 2.2587414, 12.462782), vec4(6.265566, -502.75443, -12.642513, 0.9112289), vec4(-10.983244, 20.741234, -9.701768, -0.7635988), vec4(5.383626, 1.4819539, -4.1911616, -4.8444734))
|
||||
* buf[1]
|
||||
+ mat4(vec4(12.785233, -16.345072, -0.39901125, 1.7955981), vec4(-30.48365, -1.8345358, 1.4542528, -1.1118771), vec4(19.872723, -7.337935, -42.941723, -98.52709), vec4(8.337645, -2.7312303, -2.2927687, -36.142323))
|
||||
* buf[2]
|
||||
+ mat4(vec4(-16.298317, 3.5471997, -0.44300047, -9.444417), vec4(57.5077, -35.609753, 16.163465, -4.1534753), vec4(-0.07470326, -3.8656476, -7.0901804, 3.1523974), vec4(-12.559385, -7.077619, 1.490437, -0.8211543))
|
||||
* buf[3]
|
||||
+ vec4(-7.67914, 15.927437, 1.3207729, -1.6686112);
|
||||
|
||||
buf[5] = mat4(vec4(-1.4109162, -0.372762, -3.770383, -21.367174), vec4(-6.2103205, -9.35908, 0.92529047, 8.82561), vec4(11.460242, -22.348068, 13.625772, -18.693201), vec4(-0.3429052, -3.9905605, -2.4626114, -0.45033523))
|
||||
* buf[0]
|
||||
+ mat4(vec4(7.3481627, -4.3661838, -6.3037653, -3.868115), vec4(1.5462853, 6.5488915, 1.9701879, -0.58291394), vec4(6.5858274, -2.2180402, 3.7127688, -1.3730392), vec4(-5.7973905, 10.134961, -2.3395722, -5.965605))
|
||||
* buf[1]
|
||||
+ mat4(vec4(-2.5132585, -6.6685553, -1.4029363, -0.16285264), vec4(-0.37908727, 0.53738135, 4.389061, -1.3024765), vec4(-0.70647055, 2.0111287, -5.1659346, -3.728635), vec4(-13.562562, 10.487719, -0.9173751, -2.6487076))
|
||||
* buf[2]
|
||||
+ mat4(vec4(-8.645013, 6.5546675, -6.3944063, -5.5933375), vec4(-0.57783127, -1.077275, 36.91025, 5.736769), vec4(14.283112, 3.7146652, 7.1452246, -4.5958776), vec4(2.7192075, 3.6021907, -4.366337, -2.3653464))
|
||||
* buf[3]
|
||||
+ vec4(-5.9000807, -4.329569, 1.2427121, 8.59503);
|
||||
|
||||
buf[4] = sigmoid(buf[4]);
|
||||
buf[5] = sigmoid(buf[5]);
|
||||
|
||||
buf[6] = mat4(vec4(-1.61102, 0.7970257, 1.4675229, 0.20917463), vec4(-28.793737, -7.1390953, 1.5025433, 4.656581), vec4(-10.94861, 39.66238, 0.74318546, -10.095605), vec4(-0.7229728, -1.5483948, 0.7301322, 2.1687684))
|
||||
* buf[0]
|
||||
+ mat4(vec4(3.2547753, 21.489103, -1.0194173, -3.3100595), vec4(-3.7316632, -3.3792162, -7.223193, -0.23685838), vec4(13.1804495, 0.7916005, 5.338587, 5.687114), vec4(-4.167605, -17.798311, -6.815736, -1.6451967))
|
||||
* buf[1]
|
||||
+ mat4(vec4(0.604885, -7.800309, -7.213122, -2.741014), vec4(-3.522382, -0.12359311, -0.5258442, 0.43852118), vec4(9.6752825, -22.853785, 2.062431, 0.099892326), vec4(-4.3196306, -17.730087, 2.5184598, 5.30267))
|
||||
* buf[2]
|
||||
+ mat4(vec4(-6.545563, -15.790176, -6.0438633, -5.415399), vec4(-43.591583, 28.551912, -16.00161, 18.84728), vec4(4.212382, 8.394307, 3.0958717, 8.657522), vec4(-5.0237565, -4.450633, -4.4768, -5.5010443))
|
||||
* buf[3]
|
||||
+ mat4(vec4(1.6985557, -67.05806, 6.897715, 1.9004834), vec4(1.8680354, 2.3915145, 2.5231109, 4.081538), vec4(11.158006, 1.7294737, 2.0738268, 7.386411), vec4(-4.256034, -306.24686, 8.258898, -17.132736))
|
||||
* buf[4]
|
||||
+ mat4(vec4(1.6889864, -4.5852966, 3.8534803, -6.3482175), vec4(1.3543309, -1.2640043, 9.932754, 2.9079645), vec4(-5.2770967, 0.07150358, -0.13962056, 3.3269649), vec4(28.34703, -4.918278, 6.1044083, 4.085355))
|
||||
* buf[5]
|
||||
+ vec4(6.6818056, 12.522166, -3.7075126, -4.104386);
|
||||
|
||||
buf[7] = mat4(vec4(-8.265602, -4.7027016, 5.098234, 0.7509808), vec4(8.6507845, -17.15949, 16.51939, -8.884479), vec4(-4.036479, -2.3946867, -2.6055532, -1.9866527), vec4(-2.2167742, -1.8135649, -5.9759874, 4.8846445))
|
||||
* buf[0]
|
||||
+ mat4(vec4(6.7790847, 3.5076547, -2.8191125, -2.7028968), vec4(-5.743024, -0.27844876, 1.4958696, -5.0517144), vec4(13.122226, 15.735168, -2.9397483, -4.101023), vec4(-14.375265, -5.030483, -6.2599335, 2.9848232))
|
||||
* buf[1]
|
||||
+ mat4(vec4(4.0950394, -0.94011575, -5.674733, 4.755022), vec4(4.3809423, 4.8310084, 1.7425908, -3.437416), vec4(2.117492, 0.16342592, -104.56341, 16.949184), vec4(-5.22543, -2.994248, 3.8350096, -1.9364246))
|
||||
* buf[2]
|
||||
+ mat4(vec4(-5.900337, 1.7946124, -13.604192, -3.8060522), vec4(6.6583457, 31.911177, 25.164474, 91.81147), vec4(11.840538, 4.1503043, -0.7314397, 6.768467), vec4(-6.3967767, 4.034772, 6.1714606, -0.32874924))
|
||||
* buf[3]
|
||||
+ mat4(vec4(3.4992442, -196.91893, -8.923708, 2.8142626), vec4(3.4806502, -3.1846354, 5.1725626, 5.1804223), vec4(-2.4009497, 15.585794, 1.2863957, 2.0252278), vec4(-71.25271, -62.441242, -8.138444, 0.50670296))
|
||||
* buf[4]
|
||||
+ mat4(vec4(-12.291733, -11.176166, -7.3474145, 4.390294), vec4(10.805477, 5.6337385, -0.9385842, -4.7348723), vec4(-12.869276, -7.039391, 5.3029537, 7.5436664), vec4(1.4593618, 8.91898, 3.5101583, 5.840625))
|
||||
* buf[5]
|
||||
+ vec4(2.2415268, -6.705987, -0.98861027, -2.117676);
|
||||
|
||||
buf[6] = sigmoid(buf[6]);
|
||||
buf[7] = sigmoid(buf[7]);
|
||||
|
||||
buf[0] = mat4(vec4(1.6794263, 1.3817469, 2.9625452, 0.0), vec4(-1.8834411, -1.4806935, -3.5924516, 0.0), vec4(-1.3279216, -1.0918057, -2.3124623, 0.0), vec4(0.2662234, 0.23235129, 0.44178495, 0.0))
|
||||
* buf[0]
|
||||
+ mat4(vec4(-0.6299101, -0.5945583, -0.9125601, 0.0), vec4(0.17828953, 0.18300213, 0.18182953, 0.0), vec4(-2.96544, -2.5819945, -4.9001055, 0.0), vec4(1.4195864, 1.1868085, 2.5176322, 0.0))
|
||||
* buf[1]
|
||||
+ mat4(vec4(-1.2584374, -1.0552157, -2.1688404, 0.0), vec4(-0.7200217, -0.52666044, -1.438251, 0.0), vec4(0.15345335, 0.15196142, 0.272854, 0.0), vec4(0.945728, 0.8861938, 1.2766753, 0.0))
|
||||
* buf[2]
|
||||
+ mat4(vec4(-2.4218085, -1.968602, -4.35166, 0.0), vec4(-22.683098, -18.0544, -41.954372, 0.0), vec4(0.63792, 0.5470648, 1.1078634, 0.0), vec4(-1.5489894, -1.3075932, -2.6444845, 0.0))
|
||||
* buf[3]
|
||||
+ mat4(vec4(-0.49252132, -0.39877754, -0.91366625, 0.0), vec4(0.95609266, 0.7923952, 1.640221, 0.0), vec4(0.30616966, 0.15693925, 0.8639857, 0.0), vec4(1.1825981, 0.94504964, 2.176963, 0.0))
|
||||
* buf[4]
|
||||
+ mat4(vec4(0.35446745, 0.3293795, 0.59547555, 0.0), vec4(-0.58784515, -0.48177817, -1.0614829, 0.0), vec4(2.5271258, 1.9991658, 4.6846647, 0.0), vec4(0.13042648, 0.08864098, 0.30187556, 0.0))
|
||||
* buf[5]
|
||||
+ mat4(vec4(-1.7718065, -1.4033192, -3.3355875, 0.0), vec4(3.1664357, 2.638297, 5.378702, 0.0), vec4(-3.1724713, -2.6107926, -5.549295, 0.0), vec4(-2.851368, -2.249092, -5.3013067, 0.0))
|
||||
* buf[6]
|
||||
+ mat4(vec4(1.5203838, 1.2212278, 2.8404984, 0.0), vec4(1.5210563, 1.2651345, 2.683903, 0.0), vec4(2.9789467, 2.4364579, 5.2347264, 0.0), vec4(2.2270417, 1.8825914, 3.8028636, 0.0))
|
||||
* buf[7]
|
||||
+ vec4(-1.5468478, -3.6171484, 0.24762098, 0.0);
|
||||
|
||||
buf[0] = sigmoid(buf[0]);
|
||||
return vec4(buf[0].x , buf[0].y , buf[0].z, 1.0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 uv = vUv * 2.0 - 1.0; uv.y *= -1.0;
|
||||
vec4 pattern = cppn_fn(uv, 0.1 * sin(0.3 * iTime), 0.1 * sin(0.69 * iTime), 0.1 * sin(0.44 * iTime));
|
||||
|
||||
vec3 color1 = mix(uBackgroundColor, uPrimaryCta, pattern.x);
|
||||
vec3 color2 = mix(uBackgroundColor, uAccent, pattern.y);
|
||||
vec3 color3 = mix(uBackgroundColor, uSecondaryCta, pattern.z);
|
||||
|
||||
vec3 finalColor = (color1 + color2 + color3) / 3.0;
|
||||
|
||||
gl_FragColor = vec4(finalColor, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const CPPNShaderMaterial = shaderMaterial(
|
||||
{
|
||||
iTime: 0,
|
||||
iResolution: new THREE.Vector2(1, 1),
|
||||
uBackgroundColor: new THREE.Color(0x000000),
|
||||
uPrimaryCta: new THREE.Color(0xff0000),
|
||||
uAccent: new THREE.Color(0x00ff00),
|
||||
uSecondaryCta: new THREE.Color(0x0000ff),
|
||||
},
|
||||
vertexShader,
|
||||
fragmentShader
|
||||
);
|
||||
|
||||
extend({ CPPNShaderMaterial });
|
||||
|
||||
interface ShaderPlaneProps {
|
||||
backgroundColor: THREE.Color;
|
||||
primaryCta: THREE.Color;
|
||||
accent: THREE.Color;
|
||||
secondaryCta: THREE.Color;
|
||||
}
|
||||
|
||||
const ShaderPlane = memo(({ backgroundColor, primaryCta, accent, secondaryCta }: ShaderPlaneProps) => {
|
||||
const meshRef = useRef<THREE.Mesh>(null!);
|
||||
const materialRef = useRef<THREE.ShaderMaterial & {
|
||||
iTime: number;
|
||||
iResolution: THREE.Vector2;
|
||||
uBackgroundColor: THREE.Color;
|
||||
uPrimaryCta: THREE.Color;
|
||||
uAccent: THREE.Color;
|
||||
uSecondaryCta: THREE.Color;
|
||||
}>(null!);
|
||||
const { viewport } = useThree();
|
||||
|
||||
useFrame((state) => {
|
||||
if (!materialRef.current) return;
|
||||
materialRef.current.iTime = state.clock.elapsedTime;
|
||||
const { width, height } = state.size;
|
||||
materialRef.current.iResolution.set(width, height);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!materialRef.current) return;
|
||||
materialRef.current.uBackgroundColor = backgroundColor;
|
||||
materialRef.current.uPrimaryCta = primaryCta;
|
||||
materialRef.current.uAccent = accent;
|
||||
materialRef.current.uSecondaryCta = secondaryCta;
|
||||
}, [backgroundColor, primaryCta, accent, secondaryCta]);
|
||||
|
||||
return (
|
||||
<mesh ref={meshRef} position={[0, 0, 0]}>
|
||||
<planeGeometry args={[viewport.width, viewport.height]} />
|
||||
<cPPNShaderMaterial ref={materialRef} side={THREE.DoubleSide} />
|
||||
</mesh>
|
||||
);
|
||||
});
|
||||
|
||||
ShaderPlane.displayName = 'ShaderPlane';
|
||||
|
||||
interface FluidBackgroundProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const FluidBackground = ({ className = "" }: FluidBackgroundProps) => {
|
||||
const camera = useMemo(() => ({ position: [0, 0, 5] as [number, number, number], fov: 75, near: 0.1, far: 1000 }), []);
|
||||
|
||||
const [colors, setColors] = useState({
|
||||
background: new THREE.Color(0x000000),
|
||||
primaryCta: new THREE.Color(0xff0000),
|
||||
accent: new THREE.Color(0x00ff00),
|
||||
secondaryCta: new THREE.Color(0x0000ff),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const updateColors = () => {
|
||||
setColors({
|
||||
background: getComputedColor('--background'),
|
||||
primaryCta: getComputedColor('--color-primary-cta'),
|
||||
accent: getComputedColor('--color-accent'),
|
||||
secondaryCta: getComputedColor('--color-secondary-cta'),
|
||||
});
|
||||
};
|
||||
|
||||
updateColors();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={cls("bg-background fixed inset-0 -z-10 w-full h-full", className)} aria-hidden="true">
|
||||
<Canvas
|
||||
camera={camera}
|
||||
gl={{ antialias: true, alpha: false }}
|
||||
dpr={[1, 2]}
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
>
|
||||
<ShaderPlane
|
||||
backgroundColor={colors.background}
|
||||
primaryCta={colors.primaryCta}
|
||||
accent={colors.accent}
|
||||
secondaryCta={colors.secondaryCta}
|
||||
/>
|
||||
</Canvas>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
FluidBackground.displayName = 'FluidBackground';
|
||||
|
||||
export default memo(FluidBackground);
|
||||
|
||||
declare module '@react-three/fiber' {
|
||||
interface ThreeElements {
|
||||
cPPNShaderMaterial: unknown;
|
||||
}
|
||||
}
|
||||
67
src/components/background/GradientBarsBackground.tsx
Normal file
67
src/components/background/GradientBarsBackground.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
'use client';
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import { cls } from '@/lib/utils';
|
||||
|
||||
interface GradientBarsBackgroundProps {
|
||||
className?: string;
|
||||
numBars?: number;
|
||||
gradientFrom?: string;
|
||||
gradientTo?: string;
|
||||
opacity?: number;
|
||||
}
|
||||
|
||||
const GradientBarsBackground = ({
|
||||
className = "",
|
||||
numBars = 15,
|
||||
gradientFrom = "var(--color-primary-cta)",
|
||||
gradientTo = "transparent",
|
||||
opacity = 0.5,
|
||||
}: GradientBarsBackgroundProps) => {
|
||||
const calculateHeight = (index: number, total: number): number => {
|
||||
const position = index / (total - 1);
|
||||
const maxHeight = 100;
|
||||
const minHeight = 30;
|
||||
|
||||
const center = 0.5;
|
||||
const distanceFromCenter = Math.abs(position - center);
|
||||
const heightPercentage = Math.pow(distanceFromCenter * 2, 1.2);
|
||||
|
||||
return minHeight + (maxHeight - minHeight) * heightPercentage;
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cls("fixed inset-0 -z-10 overflow-hidden", className)}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div
|
||||
className="flex h-full w-full backface-hidden antialiased"
|
||||
style={{
|
||||
transform: 'translateZ(0)',
|
||||
}}
|
||||
>
|
||||
{Array.from({ length: numBars }).map((_, index) => {
|
||||
const height = calculateHeight(index, numBars);
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className="h-full origin-bottom box-border"
|
||||
style={{
|
||||
flex: `1 0 calc(100% / ${numBars})`,
|
||||
maxWidth: `calc(100% / ${numBars})`,
|
||||
background: `linear-gradient(to top, ${gradientFrom}, ${gradientTo})`,
|
||||
transform: `scaleY(${height / 100})`,
|
||||
opacity: opacity,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
GradientBarsBackground.displayName = 'GradientBarsBackground';
|
||||
|
||||
export default memo(GradientBarsBackground);
|
||||
45
src/components/background/GridBackround.tsx
Normal file
45
src/components/background/GridBackround.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
"use client";
|
||||
|
||||
import { memo } from "react";
|
||||
import { cls } from "@/lib/utils";
|
||||
|
||||
type GridSize = "small" | "medium" | "large";
|
||||
|
||||
interface GridBackroundProps {
|
||||
size?: GridSize;
|
||||
className?: string;
|
||||
perspectiveThreeD?: boolean;
|
||||
}
|
||||
|
||||
const GRID_SIZES: Record<GridSize, string> = {
|
||||
small: "6.25vw 6.25vw",
|
||||
medium: "10vw 10vw",
|
||||
large: "20vw 20vw",
|
||||
};
|
||||
|
||||
const GridBackround = ({
|
||||
size = "medium",
|
||||
className = "",
|
||||
perspectiveThreeD = false
|
||||
}: GridBackroundProps) => {
|
||||
return (
|
||||
<div
|
||||
className={cls(
|
||||
"fixed inset-0 -z-10 bg-background [mask-image:radial-gradient(circle_at_center,white_0%,transparent_90%)]",
|
||||
perspectiveThreeD && "inset-x-0 inset-y-[-30%] h-[200%] skew-y-12",
|
||||
className
|
||||
)}
|
||||
style={{
|
||||
backgroundImage:
|
||||
"linear-gradient(to right, color-mix(in srgb, var(--background-accent) 10%, transparent) 1px, transparent 1px), linear-gradient(to bottom, color-mix(in srgb, var(--background-accent) 10%, transparent) 1px, transparent 1px)",
|
||||
backgroundSize: GRID_SIZES[size],
|
||||
backgroundRepeat: "repeat",
|
||||
}}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
GridBackround.displayName = "GridBackround";
|
||||
|
||||
export default memo(GridBackround);
|
||||
31
src/components/background/NoiseBackground.tsx
Normal file
31
src/components/background/NoiseBackground.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
"use client";
|
||||
|
||||
import React, { memo } from "react";
|
||||
import { cls } from "@/lib/utils";
|
||||
|
||||
interface NoiseBackgroundProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const NoiseBackground = ({ className = "" }: NoiseBackgroundProps) => {
|
||||
return (
|
||||
<div
|
||||
className={cls("fixed inset-0 -z-10 bg-accent/10",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="absolute inset-0 bg-repeat mix-blend-overlay opacity-12"
|
||||
style={{
|
||||
backgroundImage: "url(/images/noise.webp)",
|
||||
backgroundSize: "512px"
|
||||
}}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
NoiseBackground.displayName = "NoiseBackground";
|
||||
|
||||
export default memo(NoiseBackground);
|
||||
@@ -0,0 +1,35 @@
|
||||
"use client";
|
||||
|
||||
import React, { memo } from "react";
|
||||
import { cls } from "@/lib/utils";
|
||||
|
||||
interface NoiseDiagonalGradientBackgroundProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const NoiseDiagonalGradientBackground = ({ className = "" }: NoiseDiagonalGradientBackgroundProps) => {
|
||||
return (
|
||||
<div
|
||||
className={cls("fixed inset-0 -z-10 bg-accent/10",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="absolute inset-0 overflow-hidden pointer-events-none opacity-100 bg-gradient-to-br from-background via-accent/20 to-primary-cta/20"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<div
|
||||
className="absolute inset-0 bg-repeat mix-blend-overlay opacity-12"
|
||||
style={{
|
||||
backgroundImage: "url(/images/noise.webp)",
|
||||
backgroundSize: "512px"
|
||||
}}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
NoiseDiagonalGradientBackground.displayName = "NoiseDiagonalGradientBackground";
|
||||
|
||||
export default memo(NoiseDiagonalGradientBackground);
|
||||
35
src/components/background/NoiseGradientBackground.tsx
Normal file
35
src/components/background/NoiseGradientBackground.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
"use client";
|
||||
|
||||
import React, { memo } from "react";
|
||||
import { cls } from "@/lib/utils";
|
||||
|
||||
interface NoiseGradientBackgroundProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const NoiseGradientBackground = ({ className = "" }: NoiseGradientBackgroundProps) => {
|
||||
return (
|
||||
<div
|
||||
className={cls("fixed inset-0 -z-10 bg-accent/10",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className="absolute inset-0 overflow-hidden pointer-events-none opacity-100 bg-gradient-to-r from-background via-accent/20 to-primary-cta/20"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<div
|
||||
className="absolute inset-0 bg-repeat mix-blend-overlay opacity-12"
|
||||
style={{
|
||||
backgroundImage: "url(/images/noise.webp)",
|
||||
backgroundSize: "512px"
|
||||
}}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
NoiseGradientBackground.displayName = "NoiseGradientBackground";
|
||||
|
||||
export default memo(NoiseGradientBackground);
|
||||
21
src/components/background/PlainBackground.tsx
Normal file
21
src/components/background/PlainBackground.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
"use client";
|
||||
|
||||
import { memo } from "react";
|
||||
import { cls } from "@/lib/utils";
|
||||
|
||||
interface PlainBackgroundProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const PlainBackground = ({ className = "" }: PlainBackgroundProps) => {
|
||||
return (
|
||||
<div
|
||||
className={cls("fixed inset-0 -z-10 bg-background", className)}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
PlainBackground.displayName = "PlainBackground";
|
||||
|
||||
export default memo(PlainBackground);
|
||||
34
src/components/background/RadialGradientBackground.tsx
Normal file
34
src/components/background/RadialGradientBackground.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
'use client';
|
||||
|
||||
import React, { memo } from 'react';
|
||||
import { cls } from '@/lib/utils';
|
||||
|
||||
interface RadialGradientBackgroundProps {
|
||||
className?: string;
|
||||
centerColor?: string;
|
||||
edgeColor?: string;
|
||||
size?: string;
|
||||
position?: string;
|
||||
}
|
||||
|
||||
const RadialGradientBackground = ({
|
||||
className = "",
|
||||
centerColor = "var(--background)",
|
||||
edgeColor = "var(--color-background-accent)",
|
||||
size = "130% 130%",
|
||||
position = "50% 15%",
|
||||
}: RadialGradientBackgroundProps) => {
|
||||
return (
|
||||
<div
|
||||
className={cls("fixed top-0 left-0 right-0 bottom-0 h-screen w-full -z-10", className)}
|
||||
style={{
|
||||
background: `radial-gradient(${size} at ${position}, ${centerColor} 40%, ${edgeColor} 100%)`,
|
||||
}}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
RadialGradientBackground.displayName = 'RadialGradientBackground';
|
||||
|
||||
export default memo(RadialGradientBackground);
|
||||
@@ -0,0 +1,102 @@
|
||||
.floating-gradient-background-container {
|
||||
--circle-size: 80%;
|
||||
--circle-size-small: 60%;
|
||||
--blending: hard-light;
|
||||
}
|
||||
|
||||
.floating-gradient-background-circle-one {
|
||||
background: radial-gradient(circle at center, var(--color-background-accent) 0, rgba(255, 255, 255, 0) 50%) no-repeat;
|
||||
mix-blend-mode: var(--blending);
|
||||
width: var(--circle-size);
|
||||
height: var(--circle-size);
|
||||
top: calc(50% - var(--circle-size-small) / 2);
|
||||
left: calc(50% - var(--circle-size-small) / 2);
|
||||
transform-origin: center center;
|
||||
animation: moveVertical 20s ease infinite;
|
||||
}
|
||||
|
||||
.floating-gradient-background-circle-two {
|
||||
background: radial-gradient(circle at center, var(--color-accent) 0, rgba(255, 255, 255, 0) 50%) no-repeat;
|
||||
mix-blend-mode: var(--blending);
|
||||
width: var(--circle-size);
|
||||
height: var(--circle-size);
|
||||
top: calc(50% - var(--circle-size-small) / 2);
|
||||
left: calc(50% - var(--circle-size-small) / 2);
|
||||
transform-origin: calc(50% - 400px);
|
||||
animation: moveInCircle 20s reverse infinite;
|
||||
}
|
||||
|
||||
.floating-gradient-background-circle-three {
|
||||
background: radial-gradient(circle at center, var(--color-primary-cta) 0, rgba(255, 255, 255, 0) 50%) no-repeat;
|
||||
mix-blend-mode: var(--blending);
|
||||
width: var(--circle-size-small);
|
||||
height: var(--circle-size-small);
|
||||
top: calc(50% - var(--circle-size) / 2 + 200px);
|
||||
left: calc(50% - var(--circle-size) / 2 - 500px);
|
||||
transform-origin: calc(50% + 400px);
|
||||
animation: moveInCircle 30s linear infinite;
|
||||
}
|
||||
|
||||
.floating-gradient-background-circle-four {
|
||||
background: radial-gradient(circle at center, var(--color-background-accent) 0, rgba(255, 255, 255, 0) 50%) no-repeat;
|
||||
mix-blend-mode: var(--blending);
|
||||
width: var(--circle-size-small);
|
||||
height: var(--circle-size-small);
|
||||
top: calc(50% - var(--circle-size) / 2);
|
||||
left: calc(50% - var(--circle-size) / 2);
|
||||
transform-origin: calc(50% - 200px);
|
||||
animation: moveHorizontal 30s ease infinite;
|
||||
}
|
||||
|
||||
.floating-gradient-background-circle-five {
|
||||
background: radial-gradient(circle at center, var(--color-primary-cta) 0, rgba(255, 255, 255, 0) 50%) no-repeat;
|
||||
mix-blend-mode: var(--blending);
|
||||
width: calc(var(--circle-size-small) * 2);
|
||||
height: calc(var(--circle-size-small) * 2);
|
||||
top: calc(50% - var(--circle-size));
|
||||
left: calc(50% - var(--circle-size));
|
||||
transform-origin: calc(50% - 800px) calc(50% + 200px);
|
||||
animation: moveInCircle 20s ease infinite;
|
||||
}
|
||||
|
||||
@keyframes moveInCircle {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes moveVertical {
|
||||
0% {
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translateY(50%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes moveHorizontal {
|
||||
0% {
|
||||
transform: translateX(-50%) translateY(-10%);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translateX(50%) translateY(10%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(-50%) translateY(-10%);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
"use client";
|
||||
|
||||
import { memo } from "react";
|
||||
import { cls } from "@/lib/utils";
|
||||
import "./FloatingGradientBackground.css";
|
||||
|
||||
interface FloatingGradientBackgroundProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const FloatingGradientBackground = ({
|
||||
className = "",
|
||||
}: FloatingGradientBackgroundProps) => {
|
||||
return (
|
||||
<div
|
||||
className={cls(
|
||||
"fixed top-0 bottom-0 left-0 right-0 w-full h-full z-0 pointer-events-none blur-[40px]",
|
||||
"[mask-image:linear-gradient(to_bottom,transparent,#010101_20%,#010101_80%,transparent)]",
|
||||
"[mask-composite:intersect]",
|
||||
"[-webkit-mask-image:linear-gradient(to_bottom,transparent,#010101_20%,#010101_80%,transparent)]",
|
||||
"[-webkit-mask-composite:destination-in]",
|
||||
"floating-gradient-background-container",
|
||||
className
|
||||
)}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div className="absolute opacity-[0.075] floating-gradient-background-circle-one" />
|
||||
<div className="absolute opacity-[0.125] floating-gradient-background-circle-two" />
|
||||
<div className="absolute opacity-[0.125] floating-gradient-background-circle-three" />
|
||||
<div className="absolute opacity-[0.15] floating-gradient-background-circle-four" />
|
||||
<div className="absolute opacity-[0.075] floating-gradient-background-circle-five" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
FloatingGradientBackground.displayName = "FloatingGradientBackground";
|
||||
|
||||
export default memo(FloatingGradientBackground);
|
||||
Reference in New Issue
Block a user