nxtgauge-frontend-solid/src/components/PublicBackground.tsx

92 lines
3.6 KiB
TypeScript

import { For } from 'solid-js';
const chipNodes = [
{ kind: 'code', left: '2%', top: '14%', size: 44, cls: 'lp-chip-slow' },
{ kind: 'camera', left: '94%', top: '22%', size: 46, cls: 'lp-chip-mid' },
{ kind: 'briefcase', left: '3%', top: '76%', size: 46, cls: 'lp-chip-fast' },
{ kind: 'bell', left: '93%', top: '80%', size: 42, cls: 'lp-chip-slow' },
{ kind: 'sparkles', left: '50%', top: '6%', size: 40, cls: 'lp-chip-mid' },
] as const;
function ChipIcon(props: { kind: (typeof chipNodes)[number]['kind'] }) {
const common = { fill: 'none', stroke: 'currentColor', 'stroke-width': '2', 'stroke-linecap': 'round', 'stroke-linejoin': 'round' } as const;
if (props.kind === 'camera') {
return (
<svg viewBox="0 0 24 24" aria-hidden="true" {...common}>
<path d="M14 4a2 2 0 0 1 1.76 1.05l.49.9A2 2 0 0 0 18 7h2a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h2a2 2 0 0 0 1.76-1.05l.49-.9A2 2 0 0 1 10 4z" />
<circle cx="12" cy="13" r="3" />
</svg>
);
}
if (props.kind === 'briefcase') {
return (
<svg viewBox="0 0 24 24" aria-hidden="true" {...common}>
<path d="M16 6V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2" />
<path d="M22 13a18 18 0 0 1-20 0" />
<rect x="2" y="6" width="20" height="14" rx="2" />
</svg>
);
}
if (props.kind === 'bell') {
return (
<svg viewBox="0 0 24 24" aria-hidden="true" {...common}>
<path d="M10.3 21a2 2 0 0 0 3.4 0" />
<path d="M3.3 15.3A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.67C19.4 14 18 12.5 18 8A6 6 0 0 0 6 8c0 4.5-1.4 6-2.7 7.3" />
</svg>
);
}
if (props.kind === 'sparkles') {
return (
<svg viewBox="0 0 24 24" aria-hidden="true" {...common}>
<path d="M11 2.8a1 1 0 0 1 2 0l1 5.6a2 2 0 0 0 1.6 1.6l5.6 1a1 1 0 0 1 0 2l-5.6 1a2 2 0 0 0-1.6 1.6l-1 5.6a1 1 0 0 1-2 0l-1-5.6A2 2 0 0 0 8.4 14l-5.6-1a1 1 0 0 1 0-2l5.6-1A2 2 0 0 0 10 8.4z" />
<path d="M20 2v4M22 4h-4" />
</svg>
);
}
return (
<svg viewBox="0 0 24 24" aria-hidden="true" {...common}>
<path d="m18 16 4-4-4-4" />
<path d="m6 8-4 4 4 4" />
<path d="m14.5 4-5 16" />
</svg>
);
}
type PublicBackgroundProps = {
scrollY?: number;
reduceMotion?: boolean;
meshFactor?: number;
ribbonFactor?: number;
chipsFactor?: number;
meshCap?: number;
ribbonCap?: number;
chipsCap?: number;
};
export default function PublicBackground(props: PublicBackgroundProps) {
const y = () => (props.reduceMotion ? 0 : props.scrollY || 0);
const meshFactor = () => props.meshFactor ?? 0.1;
const ribbonFactor = () => props.ribbonFactor ?? 0.18;
const chipsFactor = () => props.chipsFactor ?? 0.24;
const meshCap = () => props.meshCap ?? 36;
const ribbonCap = () => props.ribbonCap ?? 58;
const chipsCap = () => props.chipsCap ?? 80;
return (
<div class="lp-bg" aria-hidden="true">
<div class="lp-dark-base" />
<div class="lp-mesh" style={{ transform: `translate3d(0, ${Math.min(meshCap(), y() * meshFactor())}px, 0)` }} />
<div class="lp-ribbon" style={{ transform: `translate3d(0, ${Math.min(ribbonCap(), y() * ribbonFactor())}px, 0)` }} />
<div class="lp-noise" />
<div class="lp-chips" style={{ transform: `translate3d(0, ${Math.min(chipsCap(), y() * chipsFactor())}px, 0)` }}>
<For each={chipNodes}>
{(chip) => (
<span class={`lp-chip ${chip.cls}`} style={{ left: chip.left, top: chip.top, width: `${chip.size}px`, height: `${chip.size}px` }}>
<ChipIcon kind={chip.kind} />
</span>
)}
</For>
</div>
</div>
);
}