feat(footer): reveal circuit contacts on scroll
This commit is contained in:
@@ -348,6 +348,7 @@ export function IsoSignpost({
|
|||||||
return (
|
return (
|
||||||
<g
|
<g
|
||||||
className={`iso-signpost ${isActive ? 'active' : ''}`}
|
className={`iso-signpost ${isActive ? 'active' : ''}`}
|
||||||
|
data-footer-contact={_id}
|
||||||
onMouseEnter={onMouseEnter}
|
onMouseEnter={onMouseEnter}
|
||||||
onMouseLeave={onMouseLeave}
|
onMouseLeave={onMouseLeave}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
|
|||||||
@@ -118,6 +118,66 @@
|
|||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Draw the circuit once on scroll, then reveal its four connected signposts. */
|
||||||
|
:global(html[data-motion-ready='true'])
|
||||||
|
.sceneContainer[data-footer-reveal]
|
||||||
|
:global(.footer-circuit-path) {
|
||||||
|
stroke-dasharray: 1;
|
||||||
|
stroke-dashoffset: 1;
|
||||||
|
transition: stroke-dashoffset var(--motion-duration-reveal) var(--motion-ease-in-out);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(html[data-motion-ready='true'])
|
||||||
|
.sceneContainer[data-footer-reveal][data-visible='true']
|
||||||
|
:global(.footer-circuit-path) {
|
||||||
|
stroke-dashoffset: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(html[data-motion-ready='true'])
|
||||||
|
.sceneContainer[data-footer-reveal]
|
||||||
|
:global(.iso-signpost) {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(10px);
|
||||||
|
transform-box: fill-box;
|
||||||
|
transform-origin: center bottom;
|
||||||
|
transition:
|
||||||
|
opacity var(--motion-duration-default) var(--motion-ease-out),
|
||||||
|
transform var(--motion-duration-default) var(--motion-ease-out);
|
||||||
|
transition-delay: var(--motion-duration-reveal);
|
||||||
|
will-change: opacity, transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(html[data-motion-ready='true'])
|
||||||
|
.sceneContainer[data-footer-reveal]
|
||||||
|
:global(.iso-signpost[data-footer-contact='linkedin']) {
|
||||||
|
transition-delay: calc(var(--motion-duration-reveal) + var(--motion-stagger));
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(html[data-motion-ready='true'])
|
||||||
|
.sceneContainer[data-footer-reveal]
|
||||||
|
:global(.iso-signpost[data-footer-contact='github']) {
|
||||||
|
transition-delay: calc(
|
||||||
|
var(--motion-duration-reveal) + var(--motion-stagger) + var(--motion-stagger)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(html[data-motion-ready='true'])
|
||||||
|
.sceneContainer[data-footer-reveal]
|
||||||
|
:global(.iso-signpost[data-footer-contact='telegram']) {
|
||||||
|
transition-delay: calc(
|
||||||
|
var(--motion-duration-reveal) + var(--motion-stagger) + var(--motion-stagger) +
|
||||||
|
var(--motion-stagger)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(html[data-motion-ready='true'])
|
||||||
|
.sceneContainer[data-footer-reveal][data-visible='true']
|
||||||
|
:global(.iso-signpost) {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
will-change: auto;
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
Synchronized Contact Cards Grid
|
Synchronized Contact Cards Grid
|
||||||
-------------------------------------------------------------------------- */
|
-------------------------------------------------------------------------- */
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ export default function IsometricFooter() {
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
{/* 3D Isometric SVG Scene */}
|
{/* 3D Isometric SVG Scene */}
|
||||||
<div className={styles.sceneContainer}>
|
<div className={styles.sceneContainer} data-footer-reveal>
|
||||||
<IsometricScene
|
<IsometricScene
|
||||||
activePost={activePost}
|
activePost={activePost}
|
||||||
onPostHover={setActivePost}
|
onPostHover={setActivePost}
|
||||||
|
|||||||
@@ -277,7 +277,9 @@ function CircuitConduits({ activePost }: { activePost: string | null }) {
|
|||||||
|
|
||||||
{/* Left Branch: Phone -> Step 3 -> LinkedIn -> Center Platform with exact ±0.5 slope */}
|
{/* Left Branch: Phone -> Step 3 -> LinkedIn -> Center Platform with exact ±0.5 slope */}
|
||||||
<path
|
<path
|
||||||
d="M 280,360 L 360,320 L 440,360 L 514,323"
|
d="M 514,323 L 440,360 L 360,320 L 280,360"
|
||||||
|
className="footer-circuit-path"
|
||||||
|
pathLength={1}
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="var(--accent-default, #3D8AFA)"
|
stroke="var(--accent-default, #3D8AFA)"
|
||||||
strokeWidth={2.5}
|
strokeWidth={2.5}
|
||||||
@@ -290,6 +292,8 @@ function CircuitConduits({ activePost }: { activePost: string | null }) {
|
|||||||
{/* Right Branch: Center Platform -> GitHub -> Step 5 -> Telegram with exact ±0.5 slope */}
|
{/* Right Branch: Center Platform -> GitHub -> Step 5 -> Telegram with exact ±0.5 slope */}
|
||||||
<path
|
<path
|
||||||
d="M 686,323 L 760,360 L 840,320 L 920,360"
|
d="M 686,323 L 760,360 L 840,320 L 920,360"
|
||||||
|
className="footer-circuit-path"
|
||||||
|
pathLength={1}
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="var(--accent-default, #3D8AFA)"
|
stroke="var(--accent-default, #3D8AFA)"
|
||||||
strokeWidth={2.5}
|
strokeWidth={2.5}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
const REVEAL_SELECTOR = '[data-reveal]';
|
const REVEAL_SELECTOR = '[data-reveal], [data-footer-reveal]';
|
||||||
|
|
||||||
export const MotionController = () => {
|
export const MotionController = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user