"use client"; import * as React from "react"; import { cn } from "../../lib/utils"; interface ProgressProps extends React.HTMLAttributes { /** Current progress value */ value?: number; /** Maximum progress value */ max?: number; /** Optional class name for the indicator element */ indicatorClassName?: string; /** Whether to show indeterminate loading animation */ indeterminate?: boolean; /** Color variant for the progress bar */ color?: "default" | "primary" | "secondary" | "success" | "warning" | "danger"; /** Size variant of the progress bar */ size?: "sm" | "md" | "lg"; /** Whether to show the progress value as text */ showValue?: boolean; /** Animation speed for the progress transitions */ animationSpeed?: "slow" | "normal" | "fast"; } const Progress = React.forwardRef( ({ className, value = 0, max = 100, indicatorClassName, indeterminate = false, color = "default", size = "md", showValue = false, animationSpeed = "normal", ...props }, ref) => { const percentage = value ? (value / max) * 100 : 0; const [prevPercentage, setPrevPercentage] = React.useState(percentage); const [isAnimating, setIsAnimating] = React.useState(false); React.useEffect(() => { // Only animate when the value actually changes if (percentage !== prevPercentage) { setIsAnimating(true); setPrevPercentage(percentage); // Reset the animation state after the transition is complete const timeout = setTimeout(() => { setIsAnimating(false); }, 1000); // This should match the CSS transition duration return () => clearTimeout(timeout); } }, [percentage, prevPercentage]); // Color variants const colorVariants = { default: "bg-primary", primary: "bg-primary", secondary: "bg-secondary", success: "bg-green-500", warning: "bg-yellow-500", danger: "bg-red-500" }; // Size variants const sizeVariants = { sm: "h-2", md: "h-4", lg: "h-6" }; // Animation speed variants const animationVariants = { slow: "duration-1000", normal: "duration-700", fast: "duration-300" }; return (
{showValue && (
{Math.round(percentage)}%
)}
); } ); Progress.displayName = "Progress"; export { Progress };