33 lines
1.5 KiB
React
33 lines
1.5 KiB
React
import React from "react";
|
|
|
|
const toneColor = {
|
|
accent: "var(--action-primary)",
|
|
ok: "var(--status-ok)",
|
|
warn: "var(--status-warn)",
|
|
error: "var(--status-error)",
|
|
};
|
|
|
|
/**
|
|
* Thin determinate/indeterminate progress bar — library scans, transcodes.
|
|
*/
|
|
export function ProgressBar({ value = null, tone = "accent", height = 6, showLabel = false, style = {} }) {
|
|
const c = toneColor[tone] || toneColor.accent;
|
|
const indeterminate = value == null;
|
|
const pct = Math.max(0, Math.min(100, value ?? 0));
|
|
return (
|
|
<div style={{ display: "flex", alignItems: "center", gap: "10px", ...style }}>
|
|
<div style={{ position: "relative", flex: 1, height, borderRadius: "var(--radius-pill)", background: "var(--ctv-surface-3)", overflow: "hidden" }}>
|
|
<style>{`@keyframes ctv-indet{0%{left:-40%}100%{left:100%}}`}</style>
|
|
{indeterminate ? (
|
|
<span style={{ position: "absolute", top: 0, bottom: 0, width: "40%", borderRadius: "inherit", background: c, animation: "ctv-indet 1.1s var(--ease-standard) infinite" }} />
|
|
) : (
|
|
<span style={{ position: "absolute", top: 0, left: 0, bottom: 0, width: `${pct}%`, borderRadius: "inherit", background: c, transition: "width var(--dur-slow) var(--ease-out)" }} />
|
|
)}
|
|
</div>
|
|
{showLabel && !indeterminate && (
|
|
<span style={{ font: "var(--weight-medium) var(--text-xs)/1 var(--font-mono)", color: "var(--text-secondary)", minWidth: 34, textAlign: "right", fontVariantNumeric: "tabular-nums" }}>{Math.round(pct)}%</span>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|