maitrang04's picture
Upload 91 files
d125a03 verified
import { cn } from "@/lib/utils";
type StatusType = "active" | "waiting" | "issue";
interface StatusIndicatorProps {
status: StatusType;
size?: "sm" | "md" | "lg";
showLabel?: boolean;
className?: string;
}
const statusConfig: Record<StatusType, { color: string; label: string; pulseColor: string }> = {
active: {
color: "bg-emerald-500",
label: "Active",
pulseColor: "bg-emerald-400",
},
waiting: {
color: "bg-amber-500",
label: "Waiting",
pulseColor: "bg-amber-400",
},
issue: {
color: "bg-red-500",
label: "Issue",
pulseColor: "bg-red-400",
},
};
const sizeConfig = {
sm: "h-2 w-2",
md: "h-3 w-3",
lg: "h-4 w-4",
};
export function StatusIndicator({ status, size = "md", showLabel = false, className }: StatusIndicatorProps) {
const config = statusConfig[status];
const sizeClass = sizeConfig[size];
return (
<div className={cn("flex items-center gap-2", className)} role="status" aria-label={`Status: ${config.label}`} data-testid={`status-indicator-${status}`}>
<span className="relative flex">
{status === "active" || status === "issue" ? (
<span
className={cn(
"absolute inline-flex h-full w-full animate-ping rounded-full opacity-75",
config.pulseColor
)}
/>
) : null}
<span className={cn("relative inline-flex rounded-full", sizeClass, config.color)} />
</span>
{showLabel && (
<span className="text-xs font-medium text-muted-foreground">{config.label}</span>
)}
</div>
);
}