mirror of
https://github.com/jhbruhn/respira.git
synced 2026-01-27 02:13:41 +00:00
Loading State Improvements: - Add SkeletonLoader component with pattern info, canvas, and connection skeletons - Show loading spinner on file selection and during pattern upload - Display upload progress with enhanced progress bar and percentage - Add success confirmation message when upload completes - Show thread color preview dots inline with pattern info (up to 5 colors) Visual Polish & Animations: - Add custom animations: fadeIn, slideInRight, pulseGlow, skeleton-loading - Enhance all cards with subtle hover shadow effects - Improve header with richer gradient (blue-600 → blue-700 → blue-800) - Polish error messages with icons and improved layouts - Enhance empty state with decorative patterns and feature highlights - Add smooth transitions to all NextStepGuide states - Current color block pulses with blue glow animation - Color blocks have hover states for better interactivity Pattern Upload & Lock Functionality: - Hide upload button after pattern is uploaded (patternUploaded && uploadProgress === 100) - Disable pattern dragging when uploaded with visual lock indicator - Pattern position overlay shows amber background with lock icon when locked - Pattern remains in canvas after deletion for re-editing and re-upload - Delete pattern from cache when deleting from machine to prevent auto-resume - Add LockClosedIcon to indicate locked pattern state Pattern Management: - Keep pattern data in UI after deletion for repositioning and re-uploading - Clear machine-related state but preserve pattern visualization - Reset upload progress and pattern uploaded state on deletion 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
82 lines
1.3 KiB
CSS
82 lines
1.3 KiB
CSS
@import "tailwindcss";
|
|
|
|
/* Custom animations for shimmer effect */
|
|
@keyframes shimmer {
|
|
0% {
|
|
transform: translateX(-100%);
|
|
}
|
|
100% {
|
|
transform: translateX(100%);
|
|
}
|
|
}
|
|
|
|
/* Skeleton loading animation */
|
|
@keyframes skeleton-loading {
|
|
0% {
|
|
background-position: 200% 0;
|
|
}
|
|
100% {
|
|
background-position: -200% 0;
|
|
}
|
|
}
|
|
|
|
/* Fade in animation */
|
|
@keyframes fadeIn {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(10px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
/* Slide in from right */
|
|
@keyframes slideInRight {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateX(20px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateX(0);
|
|
}
|
|
}
|
|
|
|
/* Pulse glow effect */
|
|
@keyframes pulseGlow {
|
|
0%, 100% {
|
|
box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4);
|
|
}
|
|
50% {
|
|
box-shadow: 0 0 0 8px rgba(59, 130, 246, 0);
|
|
}
|
|
}
|
|
|
|
/* Success checkmark animation */
|
|
@keyframes checkmark {
|
|
0% {
|
|
stroke-dashoffset: 100;
|
|
}
|
|
100% {
|
|
stroke-dashoffset: 0;
|
|
}
|
|
}
|
|
|
|
/* Utility classes */
|
|
.animate-fadeIn {
|
|
animation: fadeIn 0.4s ease-out;
|
|
}
|
|
|
|
.animate-slideInRight {
|
|
animation: slideInRight 0.4s ease-out;
|
|
}
|
|
|
|
.animate-pulseGlow {
|
|
animation: pulseGlow 2s ease-in-out infinite;
|
|
}
|
|
|
|
.animate-skeleton {
|
|
animation: skeleton-loading 2s ease-in-out infinite;
|
|
}
|