feat: section body animation with blur-out, delayed enter, and animation tokens

Add animation tokens to :root (--ease-spring, --ease-decelerate,
--ease-default, --duration-fast/normal/slow/spring). Apply spring easing
to section title enter. Add separate section-body transition: fast
blur-out exit (100ms), clean slide-in enter (350ms) delayed by 200ms so
content appears after the title animation completes.
This commit is contained in:
Ilia Mashkov
2026-05-13 09:39:47 +03:00
parent 481dda3c95
commit e518fc46a9
+57 -4
View File
@@ -75,6 +75,15 @@
/* === GRID === */ /* === GRID === */
--grid-gap: var(--space-3); --grid-gap: var(--space-3);
/* === ANIMATION === */
--ease-default: ease;
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
--ease-decelerate: cubic-bezier(0.25, 0, 0, 1);
--duration-fast: 100ms;
--duration-normal: 200ms;
--duration-slow: 350ms;
--duration-spring: 380ms;
} }
@theme inline { @theme inline {
@@ -235,8 +244,8 @@
opacity: 1; opacity: 1;
transform: translateY(0); transform: translateY(0);
transition: transition:
opacity 0.35s ease, opacity var(--duration-slow) var(--ease-default),
transform 0.35s ease; transform var(--duration-slow) var(--ease-default);
} }
@starting-style { @starting-style {
@@ -248,11 +257,17 @@
/* Cross-section view transition (navigation between sections) */ /* Cross-section view transition (navigation between sections) */
::view-transition-old(section-content) { ::view-transition-old(section-content) {
animation: 200ms ease both section-fade-out; animation-name: section-fade-out;
animation-duration: var(--duration-normal);
animation-timing-function: var(--ease-default);
animation-fill-mode: both;
} }
::view-transition-new(section-content) { ::view-transition-new(section-content) {
animation: 300ms ease both section-fade-in; animation-name: section-fade-in;
animation-duration: var(--duration-spring);
animation-timing-function: var(--ease-spring);
animation-fill-mode: both;
} }
@keyframes section-fade-out { @keyframes section-fade-out {
@@ -276,3 +291,41 @@
transform: translateY(0); transform: translateY(0);
} }
} }
/* Section body: instant blur-out, clean slide-in */
::view-transition-old(section-body) {
animation-name: section-body-out;
animation-duration: var(--duration-fast);
animation-timing-function: var(--ease-default);
animation-fill-mode: both;
}
::view-transition-new(section-body) {
animation-name: section-body-in;
animation-duration: var(--duration-slow);
animation-delay: var(--duration-normal);
animation-timing-function: var(--ease-decelerate);
animation-fill-mode: both;
}
@keyframes section-body-out {
from {
opacity: 1;
filter: blur(0);
}
to {
opacity: 0;
filter: blur(3px);
}
}
@keyframes section-body-in {
from {
opacity: 0;
transform: translateY(16px);
}
to {
opacity: 1;
transform: translateY(0);
}
}