5 new CSS-only animated backgrounds in the chat background picker:
- Digital Rain: two-layer vertical stripe scroll with parallax (wide
stripes at 8s, narrow at 4s via single keyframe with split positions)
- Star Drift: three-layer radial-gradient star field drifting diagonally
- Grid Pulse: neon grid lines that expand/contract (backgroundSize keyframe)
- Aurora Flow: large radial gradient bands sweeping across 200% canvas
- Fireflies: three layers of glowing dots drifting across the viewport
All use vanilla-extract keyframes (GPU-composited transforms/positions,
no canvas, no JS timers). prefers-reduced-motion is respected in
getChatBg() by stripping the animation property at call time. A "Pause
Background Animations" toggle in Settings → Appearance provides an
in-app override for the same purpose.
BG labels de-duplicated ("Digital Rain", "Star Drift", "Aurora Flow")
to avoid the duplicate "Stars" and "Aurora" entries that had appeared.
LIGHT anim-fireflies background corrected from near-black #0a0a10 to
warm white #fffdf0. Four unused keyframe exports removed from
Animations.css.ts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
108 lines
3.1 KiB
TypeScript
108 lines
3.1 KiB
TypeScript
import { keyframes, style } from '@vanilla-extract/css';
|
|
import { color, toRem } from 'folds';
|
|
|
|
const spin = keyframes({
|
|
from: { transform: 'rotate(0deg)' },
|
|
to: { transform: 'rotate(360deg)' },
|
|
});
|
|
|
|
const wobble = keyframes({
|
|
'0%': {
|
|
transform: 'translateX(0) rotateZ(0deg)',
|
|
},
|
|
'20%': {
|
|
transform: `translateX(-${toRem(4)}) rotateZ(-4deg)`,
|
|
},
|
|
'40%': {
|
|
transform: `translateX(${toRem(4)}) rotateZ(4deg)`,
|
|
},
|
|
'60%': {
|
|
transform: `translateX(-${toRem(3)}) rotateZ(-3deg)`,
|
|
},
|
|
'80%': {
|
|
transform: `translateX(${toRem(3)}) rotateZ(3deg)`,
|
|
},
|
|
'100%': {
|
|
transform: 'translateX(0) rotateZ(0deg)',
|
|
},
|
|
});
|
|
|
|
const glowPulse = keyframes({
|
|
'0%': {
|
|
boxShadow: `0 0 0 ${toRem(0)} ${color.Success.ContainerActive}`,
|
|
},
|
|
'100%': {
|
|
boxShadow: `0 0 0 ${toRem(8)} ${color.Success.ContainerActive}`,
|
|
},
|
|
});
|
|
|
|
export const WobbleAnimation = style({
|
|
animation: `${wobble} 2000ms ease-in-out`,
|
|
animationIterationCount: 'infinite',
|
|
});
|
|
|
|
export const GlowAnimation = style({
|
|
animation: `${glowPulse} 2000ms ease-out`,
|
|
animationIterationCount: 'infinite',
|
|
});
|
|
|
|
export const CallAvatarAnimation = style({
|
|
animation: `${wobble} 2000ms ease-in-out, ${glowPulse} 2000ms ease-out`,
|
|
animationIterationCount: 'infinite',
|
|
});
|
|
|
|
export const SendingSpinClass = style({
|
|
display: 'inline-block',
|
|
animation: `${spin} 900ms linear infinite`,
|
|
transformOrigin: 'center',
|
|
});
|
|
|
|
const msgAppearKeyframe = keyframes({
|
|
from: { opacity: 0.4, transform: 'scale(0.97)' },
|
|
to: { opacity: 1, transform: 'scale(1)' },
|
|
});
|
|
|
|
export const MsgAppearClass = style({
|
|
'@media': {
|
|
'(prefers-reduced-motion: no-preference)': {
|
|
animation: `${msgAppearKeyframe} 150ms ease-out both`,
|
|
},
|
|
},
|
|
});
|
|
|
|
// Animated chat background keyframes
|
|
|
|
// Animated chat background keyframes
|
|
|
|
/** Matrix rain — two stripe layers scroll at different speeds for parallax depth */
|
|
export const animRainKeyframe = keyframes({
|
|
from: { backgroundPosition: '0 0, 0 0' },
|
|
to: { backgroundPosition: '0 200px, 0 100px' },
|
|
});
|
|
|
|
/** Drifting stars — three layers drift diagonally */
|
|
export const animStarsDriftKeyframe = keyframes({
|
|
from: { backgroundPosition: '0 0, 65px 32px, 32px 97px' },
|
|
to: { backgroundPosition: '130px 130px, 195px 162px, 162px 227px' },
|
|
});
|
|
|
|
/** Grid pulse — expands/contracts backgroundSize slightly */
|
|
export const animGridPulseKeyframe = keyframes({
|
|
'0%': { backgroundSize: '60px 60px, 60px 60px, 12px 12px, 12px 12px' },
|
|
'50%': { backgroundSize: '66px 66px, 66px 66px, 13px 13px, 13px 13px' },
|
|
'100%': { backgroundSize: '60px 60px, 60px 60px, 12px 12px, 12px 12px' },
|
|
});
|
|
|
|
/** Aurora — sweeps backgroundPosition in large cycle */
|
|
export const animAuroraKeyframe = keyframes({
|
|
'0%': { backgroundPosition: '0% 0%' },
|
|
'50%': { backgroundPosition: '-50% -25%' },
|
|
'100%': { backgroundPosition: '0% 0%' },
|
|
});
|
|
|
|
/** Fireflies — three layers of glowing dots drift diagonally */
|
|
export const animFirefliesKeyframe = keyframes({
|
|
from: { backgroundPosition: '0 0, 120px 80px, 60px 140px' },
|
|
to: { backgroundPosition: '200px 150px, 320px 230px, 260px 290px' },
|
|
});
|