Co-authored-by: Jason Woltje <jason@diversecanvas.com> Co-committed-by: Jason Woltje <jason@diversecanvas.com>
54 lines
1.2 KiB
TypeScript
54 lines
1.2 KiB
TypeScript
import type { ReactElement } from "react";
|
|
|
|
export type ProgressBarVariant = "blue" | "teal" | "purple" | "amber";
|
|
|
|
export interface ProgressBarProps {
|
|
value: number; // 0-100
|
|
variant?: ProgressBarVariant;
|
|
className?: string;
|
|
label?: string; // screen reader label
|
|
}
|
|
|
|
const variantColors: Record<ProgressBarVariant, string> = {
|
|
blue: "var(--primary)",
|
|
teal: "var(--success)",
|
|
purple: "var(--purple)",
|
|
amber: "var(--warn)",
|
|
};
|
|
|
|
export function ProgressBar({
|
|
value,
|
|
variant = "blue",
|
|
className = "",
|
|
label,
|
|
}: ProgressBarProps): ReactElement {
|
|
const clampedValue = Math.min(100, Math.max(0, value));
|
|
|
|
return (
|
|
<div
|
|
className={className}
|
|
role="progressbar"
|
|
aria-valuenow={clampedValue}
|
|
aria-valuemin={0}
|
|
aria-valuemax={100}
|
|
aria-label={label}
|
|
style={{
|
|
height: 4,
|
|
borderRadius: 4,
|
|
background: "var(--surface-2)",
|
|
overflow: "hidden",
|
|
}}
|
|
>
|
|
<div
|
|
style={{
|
|
height: "100%",
|
|
borderRadius: 4,
|
|
width: `${String(clampedValue)}%`,
|
|
background: variantColors[variant],
|
|
transition: "width 0.4s ease",
|
|
}}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|