T45b Site · Iso: diagonal cells in order, the pointer meets only grown cells, motion follows the system live, replay by key, the header fits 280px

This commit is contained in:
ZacharyZhang-NY committed 2026-10-01 08:38:05 -04:00
1 parent 02c2bbe0a1
commit d05e73770f
5 files changed
+46 -13

No files matched your search

+20 -5
View File
@@ -1,16 +1,25 @@
import { useEffect, useRef } from "react";
import { useEffect, useRef, useSyncExternalStore } from "react";
import { useMode } from "../theme";
import { miniature } from "./draw";
import type { Block } from "./engine";
/** Grows once it shows, and again when pressed. */
const REDUCED = matchMedia("(prefers-reduced-motion: reduce)");
function useStill(): boolean {
return useSyncExternalStore(
(listen) => (REDUCED.addEventListener("change", listen), () => REDUCED.removeEventListener("change", listen)),
() => REDUCED.matches,
);
}
/** Grows once it shows; a press grows it again. */
export function Iso({ model, label, className }: { model: Block[]; label: string; className?: string }) {
const canvas = useRef<HTMLCanvasElement>(null);
const mini = useRef<ReturnType<typeof miniature> | null>(null);
const theme = useMode();
const still = useStill();
useEffect(() => {
const still = matchMedia("(prefers-reduced-motion: reduce)").matches;
const m = miniature(canvas.current!, model, still);
mini.current = m;
const seen = new IntersectionObserver(([e]) => e.isIntersecting && m.start(), { threshold: 0.35 });
@@ -19,9 +28,15 @@ export function Iso({ model, label, className }: { model: Block[]; label: string
seen.disconnect();
m.stop();
};
}, [model]);
}, [model, still]);
useEffect(() => mini.current?.repaint(), [theme]);
return <canvas ref={canvas} className={className} role="img" aria-label={label} onClick={() => mini.current?.replay()} />;
// Still, there is nothing to replay.
if (still) return <canvas ref={canvas} className={`iso ${className ?? ""}`} role="img" aria-label={label} />;
return (
<button className={`iso ${className ?? ""}`} aria-label={`${label}. Grow it again`} onClick={() => mini.current?.replay()}>
<canvas ref={canvas} />
</button>
);
}