turash/bugulma/frontend/components/ui/Progress.tsx

86 lines
1.9 KiB
TypeScript

import React from 'react';
import { clsx } from 'clsx';
export interface ProgressProps extends React.HTMLAttributes<HTMLDivElement> {
value: number;
max?: number;
showLabel?: boolean;
size?: 'sm' | 'md' | 'lg';
variant?: 'default' | 'success' | 'warning' | 'error';
animated?: boolean;
}
/**
* Progress bar component
*/
export const Progress = React.forwardRef<HTMLDivElement, ProgressProps>(
(
{
value,
max = 100,
showLabel = false,
size = 'md',
variant = 'default',
animated = false,
className,
...props
},
ref
) => {
const percentage = Math.min(Math.max((value / max) * 100, 0), 100);
const sizeClasses = {
sm: 'h-1',
md: 'h-2',
lg: 'h-3',
};
const variantClasses = {
default: 'bg-primary',
success: 'bg-success',
warning: 'bg-warning',
error: 'bg-destructive',
};
return (
<div
ref={ref}
className={clsx('w-full', className)}
role="progressbar"
aria-valuenow={value}
aria-valuemin={0}
aria-valuemax={max}
{...props}
>
{showLabel && (
<div className="flex justify-between items-center mb-1">
<span className="text-sm text-muted-foreground">Progress</span>
<span className="text-sm font-medium text-foreground">
{Math.round(percentage)}%
</span>
</div>
)}
<div
className={clsx(
'w-full bg-muted rounded-full overflow-hidden',
sizeClasses[size]
)}
>
<div
className={clsx(
'h-full rounded-full transition-all duration-300',
variantClasses[variant],
{
'animate-pulse': animated,
}
)}
style={{ width: `${percentage}%` }}
/>
</div>
</div>
);
}
);
Progress.displayName = 'Progress';