137 lines
5.6 KiB
TypeScript
137 lines
5.6 KiB
TypeScript
import { BRACKT_GRADIENT_START, BRACKT_GRADIENT_END } from "~/lib/brand";
|
|
|
|
export function BracketDecor({ flip = false, mobileTall = false }: { flip?: boolean; mobileTall?: boolean }) {
|
|
const base = flip ? "r" : "l";
|
|
const id = mobileTall ? `${base}-m` : base;
|
|
const W = 399;
|
|
const H = mobileTall ? 2000 : 560;
|
|
|
|
const pad = 36;
|
|
const spacing = (H - 2 * pad) / 7;
|
|
const r1Ys = Array.from({ length: 8 }, (_, i) => pad + i * spacing);
|
|
const r2Ys = [0, 1, 2, 3].map((i) => (r1Ys[i * 2] + r1Ys[i * 2 + 1]) / 2);
|
|
const r3Ys = [0, 1].map((i) => (r2Ys[i * 2] + r2Ys[i * 2 + 1]) / 2);
|
|
const champY = (r3Ys[0] + r3Ys[1]) / 2;
|
|
|
|
const x0 = 4;
|
|
const x1 = 77;
|
|
const x2 = 161;
|
|
const x3 = 252;
|
|
|
|
const gradId = `grad-${id}`;
|
|
const glowId = `glow-${id}`;
|
|
const dotsGlowId = `dots-glow-${id}`;
|
|
const finalsGlowId = `finals-glow-${id}`;
|
|
const finalsHaloId = `finals-halo-${id}`;
|
|
const finalsFadeMaskGradId = `finals-fade-mask-grad-${id}`;
|
|
const finalsFadeMaskId = `finals-fade-mask-${id}`;
|
|
const finalsLineGlowId = `finals-line-glow-${id}`;
|
|
|
|
return (
|
|
<svg
|
|
viewBox={`0 0 ${W} ${H}`}
|
|
style={{
|
|
position: "absolute",
|
|
top: "50%",
|
|
transform: `translateY(-52%)${flip ? " scaleX(-1)" : ""}`,
|
|
[flip ? "right" : "left"]: 0,
|
|
pointerEvents: "none",
|
|
height: mobileTall ? "auto" : "75vh",
|
|
width: mobileTall ? "32vw" : "auto",
|
|
}}
|
|
>
|
|
<defs>
|
|
<linearGradient id={gradId} x1="0" y1="0" x2="0" y2={H} gradientUnits="userSpaceOnUse">
|
|
<stop offset="0%" stopColor={BRACKT_GRADIENT_START} />
|
|
<stop offset="100%" stopColor={BRACKT_GRADIENT_END} />
|
|
</linearGradient>
|
|
<filter id={glowId} x="-50%" y="-50%" width="200%" height="200%">
|
|
<feGaussianBlur stdDeviation="3" result="blur" />
|
|
<feMerge>
|
|
<feMergeNode in="blur" />
|
|
<feMergeNode in="SourceGraphic" />
|
|
</feMerge>
|
|
</filter>
|
|
<filter id={finalsGlowId} filterUnits="userSpaceOnUse"
|
|
x={x2 - 15} y={r3Ys[0] - 15} width={x3 - x2 + 30} height={r3Ys[1] - r3Ys[0] + 30}>
|
|
<feGaussianBlur stdDeviation="7" result="blur" />
|
|
<feMerge>
|
|
<feMergeNode in="blur" />
|
|
<feMergeNode in="SourceGraphic" />
|
|
</feMerge>
|
|
</filter>
|
|
<filter id={finalsHaloId} filterUnits="userSpaceOnUse"
|
|
x={x2 - 40} y={r3Ys[0] - 40} width={x3 - x2 + 80} height={r3Ys[1] - r3Ys[0] + 80}>
|
|
<feGaussianBlur stdDeviation="16" />
|
|
</filter>
|
|
<linearGradient id={finalsFadeMaskGradId} x1={x3} y1="0" x2={W} y2="0" gradientUnits="userSpaceOnUse">
|
|
<stop offset="0%" stopColor="white" />
|
|
<stop offset="50%" stopColor="white" />
|
|
<stop offset="100%" stopColor="white" stopOpacity="0" />
|
|
</linearGradient>
|
|
<mask id={finalsFadeMaskId} maskUnits="userSpaceOnUse" x={x3} y={champY - 20} width={W - x3} height={40}>
|
|
<rect x="0" y="0" width={W} height={H} fill={`url(#${finalsFadeMaskGradId})`} />
|
|
</mask>
|
|
<filter id={finalsLineGlowId} filterUnits="userSpaceOnUse" x={x3 - 10} y={champY - 15} width={W - x3 + 20} height={30}>
|
|
<feGaussianBlur stdDeviation="3" result="blur" />
|
|
<feMerge>
|
|
<feMergeNode in="blur" />
|
|
<feMergeNode in="SourceGraphic" />
|
|
</feMerge>
|
|
</filter>
|
|
<filter id={dotsGlowId} x="-200%" y="-200%" width="500%" height="500%">
|
|
<feGaussianBlur stdDeviation="5" result="blur" />
|
|
<feMerge>
|
|
<feMergeNode in="blur" />
|
|
<feMergeNode in="blur" />
|
|
<feMergeNode in="SourceGraphic" />
|
|
</feMerge>
|
|
</filter>
|
|
</defs>
|
|
<g filter={`url(#${finalsHaloId})`} stroke={`url(#${gradId})`} strokeWidth={2} fill="none" opacity={0.75}>
|
|
{r3Ys.map((midY) => (
|
|
<line key={midY} x1={x2} y1={midY} x2={x3} y2={midY} />
|
|
))}
|
|
<line x1={x3} y1={r3Ys[0]} x2={x3} y2={r3Ys[1]} />
|
|
</g>
|
|
<g filter={`url(#${finalsGlowId})`} stroke={`url(#${gradId})`} strokeWidth={1.5} fill="none">
|
|
{r3Ys.map((midY) => (
|
|
<line key={midY} x1={x2} y1={midY} x2={x3} y2={midY} />
|
|
))}
|
|
<line x1={x3} y1={r3Ys[0]} x2={x3} y2={r3Ys[1]} />
|
|
</g>
|
|
<g filter={`url(#${glowId})`} stroke={`url(#${gradId})`} strokeWidth={1.5} fill="none">
|
|
{r1Ys.map((y) => (
|
|
<g key={y}>
|
|
<circle cx={x0} cy={y} r={3} fill={`url(#${gradId})`} stroke="none" filter={`url(#${dotsGlowId})`} />
|
|
<line x1={x0} y1={y} x2={x1} y2={y} />
|
|
</g>
|
|
))}
|
|
{r2Ys.map((midY, i) => (
|
|
<g key={midY}>
|
|
<line x1={x1} y1={r1Ys[i * 2]} x2={x1} y2={r1Ys[i * 2 + 1]} />
|
|
<circle cx={x1} cy={midY} r={3} fill={`url(#${gradId})`} stroke="none" filter={`url(#${dotsGlowId})`} />
|
|
<line x1={x1} y1={midY} x2={x2} y2={midY} />
|
|
</g>
|
|
))}
|
|
{r3Ys.map((midY, i) => (
|
|
<g key={midY}>
|
|
<line x1={x2} y1={r2Ys[i * 2]} x2={x2} y2={r2Ys[i * 2 + 1]} />
|
|
<circle cx={x2} cy={midY} r={3} fill={`url(#${gradId})`} stroke="none" filter={`url(#${dotsGlowId})`} />
|
|
<line x1={x2} y1={midY} x2={x3} y2={midY} />
|
|
</g>
|
|
))}
|
|
<line x1={x3} y1={r3Ys[0]} x2={x3} y2={r3Ys[1]} />
|
|
<circle cx={x3} cy={champY} r={3} fill={`url(#${gradId})`} stroke="none" filter={`url(#${dotsGlowId})`} />
|
|
</g>
|
|
<line
|
|
x1={x3} y1={champY} x2={W} y2={champY}
|
|
stroke={`url(#${gradId})`}
|
|
strokeWidth={1.5}
|
|
fill="none"
|
|
filter={`url(#${finalsLineGlowId})`}
|
|
mask={`url(#${finalsFadeMaskId})`}
|
|
/>
|
|
</svg>
|
|
);
|
|
}
|