Pulse/frontend-modern/src/styles/animations.css
2025-10-11 23:29:47 +00:00

212 lines
3.8 KiB
CSS

/* Animated Metric Container */
.metric-container {
position: relative;
display: inline-flex;
align-items: center;
overflow: visible;
min-height: 1em;
}
.metric-value {
display: inline-flex;
align-items: center;
position: relative;
z-index: 2;
}
.metric-ghost {
position: absolute;
top: 0;
left: 0;
z-index: 1;
pointer-events: none;
}
/* Ghost sliding UP and fading out (old value when increasing) */
@keyframes ghostSlideUp {
0% {
transform: translateY(0);
opacity: 1;
filter: blur(0);
}
100% {
transform: translateY(-20px);
opacity: 0;
filter: blur(2px);
}
}
/* Ghost sliding DOWN and fading out (old value when decreasing) */
@keyframes ghostSlideDown {
0% {
transform: translateY(0);
opacity: 1;
filter: blur(0);
}
100% {
transform: translateY(20px);
opacity: 0;
filter: blur(2px);
}
}
/* New value entering from below (when increasing) */
@keyframes enterFromBelow {
0% {
transform: translateY(15px);
opacity: 0;
filter: blur(1px);
color: rgb(34, 197, 94); /* green-500 */
}
50% {
color: rgb(34, 197, 94);
}
100% {
transform: translateY(0);
opacity: 1;
filter: blur(0);
color: inherit;
}
}
/* New value entering from above (when decreasing) */
@keyframes enterFromAbove {
0% {
transform: translateY(-15px);
opacity: 0;
filter: blur(1px);
color: rgb(239, 68, 68); /* red-500 */
}
50% {
color: rgb(239, 68, 68);
}
100% {
transform: translateY(0);
opacity: 1;
filter: blur(0);
color: inherit;
}
}
/* Apply animations */
.metric-ghost-up {
animation: ghostSlideUp 0.4s ease-out forwards;
color: rgb(156, 163, 175); /* gray-400 */
}
.metric-ghost-down {
animation: ghostSlideDown 0.4s ease-out forwards;
color: rgb(156, 163, 175); /* gray-400 */
}
.metric-entering-up {
animation: enterFromBelow 0.4s ease-out;
}
.metric-entering-down {
animation: enterFromAbove 0.4s ease-out;
}
/* Dark mode adjustments */
.dark .metric-ghost-up,
.dark .metric-ghost-down {
color: rgb(107, 114, 128); /* gray-500 */
}
.dark .metric-entering-up {
animation: enterFromBelowDark 0.4s ease-out;
}
.dark .metric-entering-down {
animation: enterFromAboveDark 0.4s ease-out;
}
@keyframes enterFromBelowDark {
0% {
transform: translateY(15px);
opacity: 0;
filter: blur(1px);
color: rgb(74, 222, 128); /* green-400 */
}
50% {
color: rgb(74, 222, 128);
}
100% {
transform: translateY(0);
opacity: 1;
filter: blur(0);
color: inherit;
}
}
@keyframes enterFromAboveDark {
0% {
transform: translateY(-15px);
opacity: 0;
filter: blur(1px);
color: rgb(248, 113, 113); /* red-400 */
}
50% {
color: rgb(248, 113, 113);
}
100% {
transform: translateY(0);
opacity: 1;
filter: blur(0);
color: inherit;
}
}
/* Optional: Add a subtle glow during animation */
.metric-entering-up::before,
.metric-entering-down::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 150%;
height: 150%;
pointer-events: none;
border-radius: 50%;
animation: pulseGlow 0.4s ease-out;
}
.metric-entering-up::before {
background: radial-gradient(circle, rgba(34, 197, 94, 0.3) 0%, transparent 60%);
}
.metric-entering-down::before {
background: radial-gradient(circle, rgba(239, 68, 68, 0.3) 0%, transparent 60%);
}
@keyframes pulseGlow {
0% {
opacity: 0;
transform: translate(-50%, -50%) scale(0.5);
}
50% {
opacity: 1;
}
100% {
opacity: 0;
transform: translate(-50%, -50%) scale(1.5);
}
}
/* Node row click animation */
@keyframes nodeClick {
0% {
transform: scale(1);
}
50% {
transform: scale(0.98);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
}
100% {
transform: scale(1);
}
}
.node-click {
animation: nodeClick 0.15s ease-out;
}