mirror of
https://github.com/Patiun/com.gregkilmer.www.git
synced 2026-11-08 04:08:24 +00:00
header pass
This commit is contained in:
@@ -22,21 +22,15 @@ import { useEffect, useRef } from 'react';
|
||||
interface Props {
|
||||
/** Density multiplier. 1 = default; lower for quieter sections. */
|
||||
density?: number;
|
||||
/** Tailwind/className passthrough for the root. */
|
||||
className?: string;
|
||||
/**
|
||||
* Opt-in View Transition name. DEFAULT IS UNSET so the field carries NO
|
||||
* view-transition-name. The View Transitions API requires the name to be
|
||||
* UNIQUE within a single page snapshot; assigning "sky" to every instance
|
||||
* caused "Unexpected duplicate view-transition-name: sky" + transition
|
||||
* aborts. The page should set this on AT MOST ONE field per page (typically
|
||||
* the hero), and it must match the corresponding element on the destination
|
||||
* page for the morph (e.g. constellations -> circuitry) to play.
|
||||
*
|
||||
* Set via the `data-sky` attribute + the `.vt-sky` CSS class (see global.css)
|
||||
* rather than React's inline style, which avoids an SSR/hydration mismatch.
|
||||
* Tailwind/className passthrough. The .astro call site is responsible for
|
||||
* including `vt-sky` when this element should carry the view-transition
|
||||
* morph. We do NOT compute the transition class here: conditional className
|
||||
* interpolation triggers a server/client hydration attribute mismatch under
|
||||
* Astro's client:idle. A static, fully-formed string keeps SSR and hydration
|
||||
* byte-identical.
|
||||
*/
|
||||
transitionName?: 'sky';
|
||||
className?: string;
|
||||
/** Star color theme. 'gold' leans warm, 'violet' leans mystic. */
|
||||
tint?: 'gold' | 'violet' | 'teal';
|
||||
}
|
||||
@@ -44,7 +38,6 @@ interface Props {
|
||||
export default function ConstellationField({
|
||||
density = 1,
|
||||
className = '',
|
||||
transitionName,
|
||||
tint = 'gold',
|
||||
}: Props) {
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
@@ -100,10 +93,11 @@ export default function ConstellationField({
|
||||
const cy = 0;
|
||||
const maxR = Math.sqrt(cx * cx + height * height) + 40;
|
||||
// Denser field for richer constellations. One star per ~4500 px^2, scaled
|
||||
// by density; ~15% anchors for a dense constellation backbone.
|
||||
// ~3x density for a richly star-packed sky. One star per ~1500 px^2,
|
||||
// scaled by density; ~15% anchors for a dense constellation backbone.
|
||||
const count = Math.min(
|
||||
360,
|
||||
Math.floor(((Math.PI * maxR * maxR) / 4500) * density),
|
||||
900,
|
||||
Math.floor(((Math.PI * maxR * maxR) / 1500) * density),
|
||||
);
|
||||
stars = Array.from({ length: count }, (_, i) => {
|
||||
const anchor = i % 7 === 0;
|
||||
@@ -243,15 +237,10 @@ export default function ConstellationField({
|
||||
};
|
||||
}, [density, tint]);
|
||||
|
||||
// Apply the view-transition-name via a CSS class (global.css `.vt-sky`) rather
|
||||
// than React's inline style: avoids an SSR/hydration attribute mismatch and
|
||||
// keeps the name off by default (only one field per page should opt in).
|
||||
const skyClass = transitionName === 'sky' ? 'vt-sky' : '';
|
||||
|
||||
return (
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className={`pointer-events-none absolute inset-0 h-full w-full ${skyClass} ${className}`}
|
||||
className={`pointer-events-none absolute inset-0 h-full w-full ${className}`}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user