respira/src/App.css
Jan-Henrik Bruhn c5ec118b95 Enhance UI/UX with loading states, animations, and pattern lock functionality
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>
2025-12-06 19:28:24 +01:00

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;
}