feat(seasonal): Autumn pass 2 — no tint, a gust, a real preview (#237)
CI / Build & Quality Checks (pull_request) Failing after 1m30s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Playwright smoke (e2e) (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 5s
CI / Build & Quality Checks (pull_request) Failing after 1m30s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Playwright smoke (e2e) (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 5s
Draft for human review (#237 must be approved and closed by a human). - Removed the full-screen amber wash, sun-shaft bands and vignette: they turned the user's theme beige (muddy brown on dark) and lowered contrast everywhere. The leaves carry the season on their own. Also removed the dust motes (invisible specks) and the now-unused keyframes. - Gust: every 42 s (first ~8 s after load) five leaves blow across the screen together, rising and spinning, in ~5 s. Linear timing — an eased curve is applied per keyframe segment and made them hang mid-air for a second. - Softer flutter (leaves flattened into slivers mid-flip), stronger leaf colour (opacity 0.58–0.73, less pale gold tip), brighter on dark themes. - Reduced motion on phones: no icon rail there, so the resting leaves tuck further off-edge and smaller instead of landing on the timeline icons. - Settings swatch: new optional `preview` prop on seasonal overlays; Autumn draws a warm backdrop with arranged leaves (the reduced scene rendered in the tile as a black square with two edge fragments). Rendered and inspected: light/dark/phone at 10/15/20 s, reduced on desktop and phone, gust tracked frame by frame, the Settings swatch; 60 fps with the theme on vs off (p95 frame 16.7 ms both). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
e080059f37
commit
3e132069c0
@@ -2,34 +2,22 @@ import { keyframes, style } 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.
|
||||
* `opacity` so the compositor can run them without layout or paint.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* A leaf falls from above to below the viewport while slowly turning. One tall
|
||||
* translateY serves every leaf; per-leaf duration/delay/size give parallax.
|
||||
*/
|
||||
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' },
|
||||
'6%': { opacity: '1' },
|
||||
'50%': { transform: 'translate3d(10px, 50vh, 0) rotate(160deg)' },
|
||||
'94%': { opacity: '0.9' },
|
||||
'100%': { transform: 'translate3d(-6px, 114vh, 0) rotate(340deg)', 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.
|
||||
*/
|
||||
/** Lateral sway on the leaf's wrapper so the descent reads as wind. */
|
||||
export const animLeafSway = keyframes({
|
||||
'0%': { transform: 'translate3d(0, 0, 0)' },
|
||||
'50%': { transform: 'translate3d(34px, 0, 0)' },
|
||||
@@ -37,68 +25,40 @@ export const animLeafSway = keyframes({
|
||||
});
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Soft flutter on the blade. [#237] Gentler than before (scaleX 0.82 made
|
||||
* leaves flatten into slivers mid-flip).
|
||||
*/
|
||||
export const animLeafFlutter = keyframes({
|
||||
'0%': { transform: 'rotate(-8deg) scaleX(1)' },
|
||||
'50%': { transform: 'rotate(8deg) scaleX(0.82)' },
|
||||
'100%': { transform: 'rotate(-8deg) scaleX(1)' },
|
||||
'0%': { transform: 'rotate(-10deg) scaleX(1)' },
|
||||
'50%': { transform: 'rotate(10deg) scaleX(0.92)' },
|
||||
'100%': { transform: 'rotate(-10deg) 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.
|
||||
* [#237] A gust: the leaf enters from the left, is blown across and up while
|
||||
* spinning, and leaves on the right in ~6 s (14 % of a 42 s cycle). The rest
|
||||
* of the cycle it waits off-screen, invisible.
|
||||
*/
|
||||
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' },
|
||||
export const animGust = keyframes({
|
||||
'0%': { transform: 'translate3d(-12vw, 0, 0) rotate(0deg)', opacity: '0' },
|
||||
'1%': { opacity: '1' },
|
||||
// Fast in, then carried steadily across and up (linear timing: an eased
|
||||
// curve would apply per segment and stop the leaves mid-air).
|
||||
'3.5%': { transform: 'translate3d(22vw, -3vh, 0) rotate(200deg)' },
|
||||
'8%': { transform: 'translate3d(62vw, -12vh, 0) rotate(420deg)' },
|
||||
'12.5%': { opacity: '1' },
|
||||
'14%': { transform: 'translate3d(112vw, -24vh, 0) rotate(700deg)', opacity: '0' },
|
||||
'100%': { transform: 'translate3d(112vw, -24vh, 0) rotate(700deg)', opacity: '0' },
|
||||
});
|
||||
|
||||
/**
|
||||
* 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' },
|
||||
});
|
||||
|
||||
/**
|
||||
* [#237] Leaf blade. On the dark themes the crimson/russet leaves sank into the
|
||||
* dark warm wash, so they are lifted there (brightness only, no layout/paint
|
||||
* cost beyond the existing layer).
|
||||
* Leaf blade. On the dark themes the crimson/russet leaves sank into the
|
||||
* background, so they are lifted there.
|
||||
*/
|
||||
export const leafBlade = style({
|
||||
selectors: {
|
||||
'body.dark-theme &, body.butter-theme &': {
|
||||
filter: 'brightness(1.45) saturate(1.15) drop-shadow(0 1px 2px oklch(0.15 0.04 40 / 0.5))',
|
||||
filter: 'brightness(1.6) saturate(1.2)',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user