samihalawa's picture
feat: Enhance UI with visual feedback during AI operations
7017720
import { useState, useEffect } from "react";
/**
* Enhanced loading component with visual feedback
*
* Features:
* - Progress indicator with percentage display
* - Animated loading spinner
* - Progress bar visualization
* - Contextual status messages
* - Animated ellipsis for active feedback
*
* @param progress - Current progress percentage (0-100)
* @param showDetails - Whether to show detailed status messages
*/
function Loading({ progress = 0, showDetails = false }: { progress?: number; showDetails?: boolean }) {
const [dots, setDots] = useState("");
// Animated dots for the loading text (provides visual feedback even when progress is unknown)
useEffect(() => {
const interval = setInterval(() => {
setDots(prev => (prev.length >= 3 ? "" : prev + "."));
}, 400);
return () => clearInterval(interval);
}, []);
// Get appropriate status message based on current progress
const getStatusMessage = () => {
if (progress < 25) return "Analyzing request...";
if (progress < 50) return "Generating content...";
if (progress < 75) return "Processing changes...";
if (progress < 100) return "Finalizing...";
return "Complete!";
};
return (
<div className="absolute left-0 top-0 h-full w-full flex flex-col items-center justify-center bg-gray-950/90 backdrop-blur-sm z-20">
<div className="relative">
{/* Progress circle with animated spin */}
<svg
className="size-16 animate-spin text-purple-400"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
{/* Progress percentage in center - only shown when progress is known */}
{progress > 0 && (
<div className="absolute inset-0 flex items-center justify-center">
<span className="text-sm font-bold text-white">{progress}%</span>
</div>
)}
</div>
<div className="mt-4 flex flex-col items-center">
{/* Main loading message with animated dots */}
<p className="text-lg font-bold text-purple-200 mb-1">AI is thinking{dots}</p>
{/* Horizontal progress bar - only shown when progress is known */}
{progress > 0 && (
<div className="w-48 h-1.5 bg-gray-700 rounded-full overflow-hidden mt-2">
<div
className="h-full bg-gradient-to-r from-purple-400 to-pink-500 transition-all duration-300 ease-out"
style={{ width: `${progress}%` }}
/>
</div>
)}
{/* Optional detailed status message - shows processing stage */}
{showDetails && (
<p className="mt-2 text-xs text-purple-300/80 max-w-xs text-center animate-pulse">
{getStatusMessage()}
</p>
)}
</div>
</div>
);
}
export default Loading;