initial commit
This commit is contained in:
commit
3ba76b4f02
90 changed files with 12507 additions and 0 deletions
63
src/components/islands/HeroZone.tsx
Normal file
63
src/components/islands/HeroZone.tsx
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import { useEffect, useRef } from "react";
|
||||
|
||||
/**
|
||||
* The reserved interactive zone on the home page.
|
||||
* Shows a warm chiaroscuro panel whose light source drifts toward the pointer —
|
||||
* the one signature motion moment per the brand brief. Future interactive pieces
|
||||
* drop into this same clipped frame.
|
||||
*
|
||||
* Respects prefers-reduced-motion: static gradient at the rest position.
|
||||
*/
|
||||
export default function HeroZone() {
|
||||
const frameRef = useRef<HTMLDivElement | null>(null);
|
||||
const accentRef = useRef<HTMLImageElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const frame = frameRef.current;
|
||||
const accent = accentRef.current;
|
||||
if (!frame) return;
|
||||
|
||||
const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||||
const rest = { x: 0.62, y: 0.28 };
|
||||
|
||||
function paint(x: number, y: number) {
|
||||
if (!frame) return;
|
||||
const lx = 30 + x * 50;
|
||||
const ly = 8 + y * 40;
|
||||
frame.style.background =
|
||||
`radial-gradient(120% 95% at ${lx}% ${ly}%, ` +
|
||||
`#C9B299 0%, #8A6A47 30%, #4A3826 60%, #221E18 92%)`;
|
||||
if (accent) {
|
||||
accent.style.transform = `translate(${(0.5 - x) * 26}px, ${(0.5 - y) * 16}px)`;
|
||||
}
|
||||
}
|
||||
|
||||
paint(rest.x, rest.y);
|
||||
if (reduce) return;
|
||||
|
||||
const onMove = (e: MouseEvent) => {
|
||||
const r = frame.getBoundingClientRect();
|
||||
paint(
|
||||
Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)),
|
||||
Math.min(1, Math.max(0, (e.clientY - r.top) / r.height)),
|
||||
);
|
||||
};
|
||||
const onLeave = () => paint(rest.x, rest.y);
|
||||
|
||||
frame.addEventListener("mousemove", onMove);
|
||||
frame.addEventListener("mouseleave", onLeave);
|
||||
return () => {
|
||||
frame.removeEventListener("mousemove", onMove);
|
||||
frame.removeEventListener("mouseleave", onLeave);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="hzframe" ref={frameRef}>
|
||||
<div className="grain" />
|
||||
<img ref={accentRef} className="hzaccent" src="/assets/accent-ringdots.svg" alt="" />
|
||||
<img className="hzwm" src="/assets/mark-rings.svg" alt="" />
|
||||
<span className="hztag">Interactive · soon</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue