Progress
Progress bars communicate completion, score, quality, and acceptance rates. All progress bars animate their width change automatically via CSS transitions.
Anatomy
┌──────────────────────────────────────────────────────┐ ← .progress-bar (track)
│▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░ │ ← .progress-bar-fill + .progress-bar-{color}
└──────────────────────────────────────────────────────┘
Basic Usage
{/* Static color */}
<div className="progress-bar">
<div className="progress-bar-fill progress-bar-accent" style={{ width: "72%" }} />
</div>
{/* Dynamic semantic color */}
<div className="progress-bar">
<div
className="progress-bar-fill"
style={{
width: `${score}%`,
background: score >= 80 ? "var(--success-color)"
: score >= 60 ? "var(--warning-color)"
: "var(--error-color)"
}}
/>
</div>
{/* Class-based color */}
<div className="progress-bar">
<div
className={`progress-bar-fill ${score >= 80 ? "progress-bar-success" : score >= 60 ? "progress-bar-warning" : "progress-bar-danger"}`}
style={{ width: `${score}%` }}
/>
</div>
CSS Definitions
/* Track */
.progress-bar { height: 6px; background: var(--bg-primary); border-radius: var(--radius-xs); overflow: hidden; }
.progress-bar-sm { height: 3px; }
.progress-bar-lg { height: 8px; }
/* Fill */
.progress-bar-fill { height: 100%; border-radius: var(--radius-xs); transition: width var(--transition-smooth); }
.progress-bar-success { background: var(--success-color); }
.progress-bar-warning { background: var(--warning-color); }
.progress-bar-danger { background: var(--error-color); }
.progress-bar-info { background: var(--info-color); }
.progress-bar-accent { background: var(--accent-color); }
Size Variants
Class Height Use
progress-bar 6px Default — scores, progress, acceptance rates
progress-bar-sm 3px Very compact rows, minimal visual weight
progress-bar-lg 8px Emphasis (overall score, primary metric)
{/* Full row with value label */}
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
<div className="progress-bar" style={{ flex: 1 }}>
<div className="progress-bar-fill progress-bar-success" style={{ width: "82%" }} />
</div>
<span style={{ fontSize: "var(--font-size-xs)", fontWeight: "var(--font-semibold)", color: "var(--text-success)", minWidth: 32 }}>
82%
</span>
</div>
Confidence Bar (AI predictions)
const confColor = (c: number) =>
c > 0.85 ? "var(--success-color)"
: c > 0.70 ? "var(--warning-color)"
: "var(--error-color)";
<div style={{ display: "flex", alignItems: "center", gap: 8 }}>
<div className="progress-bar" style={{ flex: 1 }}>
<div
className="progress-bar-fill"
style={{ width: `${prediction.confidence * 100}%`, background: confColor(prediction.confidence) }}
/>
</div>
<span style={{
fontSize: "var(--font-size-xs)",
fontWeight: "var(--font-semibold)",
color: confColor(prediction.confidence),
minWidth: 32,
}}>
{(prediction.confidence * 100).toFixed(0)}%
</span>
</div>
Score Bar (health / quality)
const scoreColor = (s: number) =>
s >= 80 ? "var(--success-color)"
: s >= 60 ? "var(--warning-color)"
: "var(--error-color)";
{/* Inside a panel-card */}
<div className="panel-row" style={{ marginBottom: 6 }}>
<span style={{ fontWeight: "var(--font-semibold)" }}>{dimension.name}</span>
<span style={{ marginLeft: "auto", color: scoreColor(dimension.score), fontWeight: "var(--font-semibold)" }}>
{dimension.score.toFixed(0)}/100
</span>
</div>
<div className="progress-bar" style={{ marginBottom: 6 }}>
<div
className="progress-bar-fill"
style={{ width: `${dimension.score}%`, background: scoreColor(dimension.score) }}
/>
</div>
Stacked / Multi-segment Bar
For showing code composition (code / comments / blank):
<div style={{ display: "flex", height: 6, borderRadius: "var(--radius-xs)", overflow: "hidden", background: "var(--bg-primary)" }}>
<div style={{ width: `${codePct}%`, background: "var(--accent-blue)" }} />
<div style={{ width: `${commentPct}%`, background: "var(--accent-green)" }} />
<div style={{ width: `${blankPct}%`, background: "var(--bg-tertiary)" }} />
</div>
Minimum Width
Always set a minimum width so empty bars are visible:
const barWidth = Math.max(4, Math.round((value / max) * 100));
<div className="progress-bar-fill progress-bar-accent" style={{ width: `${barWidth}%` }} />
Math.max(4, ...) ensures even zero-ish values show a 4% sliver.
Rules
Do
- Use
progress-bar+progress-bar-fillalways as a pair - Add a semantic fill class (
progress-bar-successetc.) or inlinebackground - Use
Math.max(4, ...)for minimum visible width - Use
flex: 1on the track when placing beside a label in a row - Keep bars in
panel-cardor below apanel-row— never standalone in a body
Don’t
// Inline bar from scratch
<div style={{ height: 6, background: "var(--bg-primary)", borderRadius: 2, overflow: "hidden" }}>
<div style={{ width: "60%", height: "100%", background: "#4caf50", borderRadius: 2 }} />
</div>
// → use .progress-bar + .progress-bar-fill.progress-bar-success
// No minimum width
<div className="progress-bar-fill" style={{ width: `${v/total*100}%` }} /> // can be 0%
// Wrong track color
<div style={{ height: 6, background: "var(--bg-tertiary)", ... }} /> // use --bg-primary for track