feat: binary glow effects, refined drawings and calls to action
Dark surfaces now carry light: frames glow along their edge and shed binary digits (BitAura), dark sections open with a lit seam (BitSeam), the career path is a line of light and "My work" became a dark stage. Buttons carry a travelling light and a spot that follows the pointer (BitGlow). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
const SURFACE = "[data-glow]";
|
||||
|
||||
/**
|
||||
* BitGlow: a light that follows the pointer across every `data-glow` surface.
|
||||
* It only publishes the pointer position as `--gx` / `--gy` on those surfaces;
|
||||
* the light itself is drawn in CSS by a `.bit-glow` child (see globals.css).
|
||||
* Purely decorative, and off when reduced motion is requested.
|
||||
*/
|
||||
export const BitGlow: React.FC = () => {
|
||||
React.useEffect(() => {
|
||||
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
||||
|
||||
let frame = 0;
|
||||
let latest: PointerEvent | null = null;
|
||||
|
||||
const publish = () => {
|
||||
frame = 0;
|
||||
if (!latest) return;
|
||||
const { clientX, clientY, target } = latest;
|
||||
let surface =
|
||||
target instanceof Element ? target.closest<HTMLElement>(SURFACE) : null;
|
||||
// Surfaces nest (a button inside a dark section): each one gets its own position.
|
||||
while (surface) {
|
||||
const rect = surface.getBoundingClientRect();
|
||||
surface.style.setProperty("--gx", `${clientX - rect.left}px`);
|
||||
surface.style.setProperty("--gy", `${clientY - rect.top}px`);
|
||||
surface =
|
||||
surface.parentElement?.closest<HTMLElement>(SURFACE) ?? null;
|
||||
}
|
||||
};
|
||||
|
||||
const onPointerMove = (event: PointerEvent) => {
|
||||
latest = event;
|
||||
if (frame === 0) frame = window.requestAnimationFrame(publish);
|
||||
};
|
||||
|
||||
window.addEventListener("pointermove", onPointerMove, { passive: true });
|
||||
return () => {
|
||||
window.removeEventListener("pointermove", onPointerMove);
|
||||
if (frame !== 0) window.cancelAnimationFrame(frame);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
};
|
||||
Reference in New Issue
Block a user