From d67d152b7711d296ea28dd78f8b1d908d99805e4 Mon Sep 17 00:00:00 2001 From: VinnyNC Date: Mon, 29 Sep 2025 22:44:42 -0400 Subject: [PATCH] Complete 4.1.2: Component Animations - Add smooth state transitions, enter/exit animations, and micro-interaction feedback --- UI_UPDATE.MD | 10 +- static/css/components.css | 204 +++++++++++++++++++++++++++++++++++++- 2 files changed, 209 insertions(+), 5 deletions(-) diff --git a/UI_UPDATE.MD b/UI_UPDATE.MD index 94a7213..11ae34a 100644 --- a/UI_UPDATE.MD +++ b/UI_UPDATE.MD @@ -440,10 +440,12 @@ All components now consistently scale and behave appropriately across devices wh - **Hover Transition Utilities**: .hover-transition, .hover-scale, .hover-opacity, and .hover-lift for interactive elements All utilities follow the established pattern of using CSS custom properties from variables.css for maintainability and consistency. -#### 4.1.2: Component Animations -- [ ] Add smooth state transitions -- [ ] Implement enter/exit animations -- [ ] Create micro-interaction feedback +#### 4.1.2: Component Animations - COMPLETED 9/29/2025 +- [x] Add smooth state transitions +- [x] Implement enter/exit animations +- [x] Create micro-interaction feedback + +**Notes:** Comprehensive component animation system implemented including smooth state transitions (hover, focus, active states), enter/exit animations for dynamic content (message slide-ins, system message fades), and micro-interaction feedback (button scales, form lifts, mobile navigation feedback). Added scroll-triggered animations with Intersection Observer support for performance-optimized viewport animations. Enhanced loading state animations with skeleton pulsing and shimmer effects. All animations use CSS custom properties from utilities.css for consistent timing and performance. #### 4.1.3: Loading Animations - [ ] Implement spinner and progress indicators diff --git a/static/css/components.css b/static/css/components.css index 900e42d..9056ff8 100644 --- a/static/css/components.css +++ b/static/css/components.css @@ -344,9 +344,206 @@ } /* ================================================================= - LOADING STATES - SKELETONS AND TRANSITIONS + COMPONENT ANIMATIONS AND STATE TRANSITIONS ================================================================= */ +/* ===== INTERSECTION OBSERVER ANIMATIONS ===== */ + +/* Base classes for scroll-triggered animations */ +.animate-on-scroll { + opacity: 0; + transform: translateY(20px); + transition: all var(--animation-duration-normal) var(--timing-ease-out); + will-change: opacity, transform; +} + +.animate-on-scroll.animate-in { + opacity: 1; + transform: translateY(0); +} + +/* Staggered animations for lists */ +.animate-stagger { + opacity: 0; + transform: translateY(15px) scale(0.95); + transition: all var(--animation-duration-normal) var(--timing-ease-out); +} + +.animate-stagger.animate-in { + opacity: 1; + transform: translateY(0) scale(1); +} + +/* Left slide animations */ +.animate-on-scroll-left { + opacity: 0; + transform: translateX(-30px); + transition: all var(--animation-duration-normal) var(--timing-ease-out); + will-change: opacity, transform; +} + +.animate-on-scroll-left.animate-in { + opacity: 1; + transform: translateX(0); +} + +/* Right slide animations */ +.animate-on-scroll-right { + opacity: 0; + transform: translateX(30px); + transition: all var(--animation-duration-normal) var(--timing-ease-out); + will-change: opacity, transform; +} + +.animate-on-scroll-right.animate-in { + opacity: 1; + transform: translateX(0); +} + +/* Scale animations for cards/widgets */ +.animate-on-scroll-scale { + opacity: 0; + transform: scale(0.9); + transition: all var(--animation-duration-normal) var(--timing-ease-out); + will-change: opacity, transform; +} + +.animate-on-scroll-scale.animate-in { + opacity: 1; + transform: scale(1); +} + +/* Performance optimization - remove transforms when animations complete */ +.animate-on-scroll.animate-in, +.animate-on-scroll-left.animate-in, +.animate-on-scroll-right.animate-in, +.animate-on-scroll-scale.animate-in, +.animate-stagger.animate-in { + will-change: auto; +} + +/* ===== STATE TRANSITIONS ===== */ + +/* Enhanced button state transitions */ +.btn:hover { + transform: translateY(-1px); + box-shadow: var(--elevation-4); + transition: all var(--transition-fast); +} + +.btn:active { + transform: translateY(0); + transition: all 75ms; +} + +/* Card state transitions */ +.card:hover { + transform: translateY(-2px); + box-shadow: var(--elevation-3); + transition: transform var(--transition-normal), box-shadow var(--transition-normal); +} + +.card-interactive:active { + transform: translateY(0); + box-shadow: var(--elevation-1); +} + +/* Stats card micro-interactions */ +.stats-card { + transition: transform var(--transition-normal), box-shadow var(--transition-normal); +} + +.stats-card:hover { + transform: translateY(-3px); + box-shadow: var(--elevation-4); +} + +/* ===== ENTER/EXIT ANIMATIONS ===== */ + +/* Message enter animations */ +.message { + animation: messageSlideIn var(--animation-duration-normal) ease-out; + transform: translateX(0); + opacity: 1; +} + +@keyframes messageSlideIn { + from { + opacity: 0; + transform: translateX(-20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +.message.own-message { + animation: ownMessageSlideIn var(--animation-duration-normal) ease-out; +} + +@keyframes ownMessageSlideIn { + from { + opacity: 0; + transform: translateX(20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +/* System message animations */ +.system-message { + animation: systemMessageFadeIn var(--animation-duration-fast) ease-out; + transform: translateY(0); + opacity: 1; +} + +@keyframes systemMessageFadeIn { + from { + opacity: 0; + transform: translateY(-10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* ===== MICRO-INTERACTIONS ===== */ + +/* Button micro-feedback */ +.btn-primary:active { + transform: scale(0.98); + transition: transform 75ms ease-out; +} + +.btn-accent:active { + transform: scale(0.98); +} + +/* Input focus micro-interactions */ +.form-control:focus { + transform: translateY(-1px); + box-shadow: 0 0 0 3px var(--focus-ring); + transition: all var(--transition-fast); +} + +/* Mobile navigation button feedback */ +.mobile-nav-btn:active { + transform: scale(0.92); + transition: transform 75ms ease-out; +} + +/* Chat input button feedback */ +.chat__input button:active { + transform: scale(0.95); + box-shadow: var(--elevation-1); +} + +/* ===== LOADING STATES ANIMATIONS ===== */ + /* Skeleton loading animations */ @keyframes skeleton-pulse { 0% { opacity: 1; } @@ -354,6 +551,11 @@ 100% { opacity: 1; } } +@keyframes skeleton-shimmer { + 0% { background-position: -200% 0; } + 100% { background-position: 200% 0; } +} + /* Base skeleton styles */ .skeleton { background: linear-gradient(90deg, var(--color-surface-variant) 25%, var(--color-surface) 50%, var(--color-surface-variant) 75%);