92 lines
3.5 KiB
TypeScript
92 lines
3.5 KiB
TypeScript
|
|
import { keyframes } from '@vanilla-extract/css';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Autumn overlay keyframes. Every animation touches ONLY `transform` and
|
||
|
|
* `opacity` so the compositor can run them on the GPU without triggering
|
||
|
|
* layout or paint. keyframes() returns the generated animation-name string,
|
||
|
|
* which is applied inline in Autumn.tsx.
|
||
|
|
*
|
||
|
|
* Motion philosophy: warm, slow, cozy. Leaves tumble and rotate as they fall
|
||
|
|
* with a per-leaf sway decoupled on a wrapper; sun shafts breathe; dust motes
|
||
|
|
* drift up through the light; the whole frame has a barely-there warm pulse.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/**
|
||
|
|
* A leaf falls from above to below the viewport while continuously rotating.
|
||
|
|
* A single tall translateY serves every leaf — per-leaf duration/delay/scale
|
||
|
|
* create the parallax variety. Horizontal travel is intentionally small here
|
||
|
|
* because the real lateral motion comes from the sway wrapper below.
|
||
|
|
*/
|
||
|
|
export const animLeafFall = keyframes({
|
||
|
|
'0%': { transform: 'translate3d(0, -12vh, 0) rotate(-30deg)', opacity: '0' },
|
||
|
|
'8%': { opacity: '1' },
|
||
|
|
'50%': { transform: 'translate3d(10px, 50vh, 0) rotate(200deg)' },
|
||
|
|
'92%': { opacity: '0.85' },
|
||
|
|
'100%': { transform: 'translate3d(-6px, 114vh, 0) rotate(430deg)', opacity: '0' },
|
||
|
|
});
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Lateral sway applied to a leaf's wrapper so the descent reads as wind
|
||
|
|
* catching the blade. Decoupled from the fall so the two compose into an
|
||
|
|
* organic, non-repeating-looking path.
|
||
|
|
*/
|
||
|
|
export const animLeafSway = keyframes({
|
||
|
|
'0%': { transform: 'translate3d(0, 0, 0)' },
|
||
|
|
'50%': { transform: 'translate3d(34px, 0, 0)' },
|
||
|
|
'100%': { transform: 'translate3d(0, 0, 0)' },
|
||
|
|
});
|
||
|
|
|
||
|
|
/**
|
||
|
|
* A second flutter on the leaf's inner shape: a gentle skew/scale wobble that
|
||
|
|
* mimics the blade catching air as it spins. Cheap, transform-only.
|
||
|
|
*/
|
||
|
|
export const animLeafFlutter = keyframes({
|
||
|
|
'0%': { transform: 'rotate(-8deg) scaleX(1)' },
|
||
|
|
'50%': { transform: 'rotate(8deg) scaleX(0.82)' },
|
||
|
|
'100%': { transform: 'rotate(-8deg) scaleX(1)' },
|
||
|
|
});
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Low-sun light shaft: a long soft beam slowly slides and breathes. Uses
|
||
|
|
* translateX + opacity (never background-position) so it stays on the
|
||
|
|
* compositor. Scale on Y makes the beam subtly elongate as it brightens.
|
||
|
|
*/
|
||
|
|
export const animSunShaft = keyframes({
|
||
|
|
'0%': { transform: 'translate3d(-4%, 0, 0) scaleY(1)', opacity: '0.4' },
|
||
|
|
'50%': { transform: 'translate3d(4%, 0, 0) scaleY(1.06)', opacity: '0.75' },
|
||
|
|
'100%': { transform: 'translate3d(-4%, 0, 0) scaleY(1)', opacity: '0.4' },
|
||
|
|
});
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Dust / pollen mote: a tiny speck drifts upward through the light, swaying,
|
||
|
|
* pulsing softly in brightness as it catches the sun. transform + opacity.
|
||
|
|
*/
|
||
|
|
export const animMoteDrift = keyframes({
|
||
|
|
'0%': { transform: 'translate3d(0, 0, 0) scale(0.7)', opacity: '0' },
|
||
|
|
'15%': { opacity: '0.85' },
|
||
|
|
'40%': { transform: 'translate3d(16px, -30vh, 0) scale(1)' },
|
||
|
|
'70%': { transform: 'translate3d(-12px, -58vh, 0) scale(0.85)', opacity: '0.6' },
|
||
|
|
'90%': { opacity: '0.2' },
|
||
|
|
'100%': { transform: 'translate3d(10px, -84vh, 0) scale(0.6)', opacity: '0' },
|
||
|
|
});
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Independent twinkle for motes — a brightness flicker layered on the drift so
|
||
|
|
* specks shimmer as if turning in the light. Opacity only.
|
||
|
|
*/
|
||
|
|
export const animMoteTwinkle = keyframes({
|
||
|
|
'0%': { opacity: '0.5' },
|
||
|
|
'50%': { opacity: '1' },
|
||
|
|
'100%': { opacity: '0.5' },
|
||
|
|
});
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Barely-there breathing of the warm vignette frame so the static tint feels
|
||
|
|
* alive without any distracting motion. Opacity only.
|
||
|
|
*/
|
||
|
|
export const animEmberPulse = keyframes({
|
||
|
|
'0%': { opacity: '0.82' },
|
||
|
|
'50%': { opacity: '1' },
|
||
|
|
'100%': { opacity: '0.82' },
|
||
|
|
});
|