React Bootstrap Progress Bar
A React Bootstrap progress bar in AdminKit PRO: the width and aria-valuenow from one value, labels, sizes, colors, stripes and stacked bars.
This component is only available in AdminKit PRO. Learn more.
Use a progress bar when you know how far something has come: an upload, a list of tasks, a storage quota. In AdminKit you see them on the project cards, the settings page and the CRM and analytics dashboards.
There is no progress component to import. You write Bootstrap's .progress markup in JSX and give it one number from your props or state. That number sets both the width of the bar and its aria-valuenow, so what people see and what screen readers announce stay the same. Progress bars are part of the PRO version of AdminKit for React.
Example
export function UploadProgress({ value }: { value: number }) {
return (
<div
className="progress"
role="progressbar"
aria-label="Upload"
aria-valuenow={value}
aria-valuemin={0}
aria-valuemax={100}
>
<div className="progress-bar" style={{ width: `${value}%` }} />
</div>
);
}In JSX, the aria-value* attributes take numbers and style takes an object. That is why the width is a template string: style={{ width: `${value}%` }}. When the value changes, the bar slides to its new width with Bootstrap's transition.
Classes
| Class | Effect |
|---|---|
progress | The track, 1rem high; it carries role="progressbar" and the aria-value* attributes |
progress-bar | The filled part; its width is the value |
progress-sm, progress-lg | AdminKit: a 0.4rem or 1.5rem high track |
bg-<color> | The bar color: bg-success, bg-warning, ... |
progress-bar-striped | Stripes over the bar color |
progress-bar-animated | Moves the stripes |
progress-stacked | Holds several .progress elements as segments of one bar |
Value from a quota
A quota is rarely a percentage, so you convert it first. The billing card of the settings page shows storage this way. Each bar has a visible label that aria-labelledby points to:
export function StorageUsage({ used, total }: { used: number; total: number }) {
const percent = Math.min(Math.round((used / total) * 100), 100);
return (
<>
<div className="d-flex justify-content-between mb-1">
<span id="storage-label">Storage</span>
<span className="text-body-secondary">
{used} GB of {total} GB
</span>
</div>
<div
className="progress progress-sm"
role="progressbar"
aria-labelledby="storage-label"
aria-valuenow={percent}
aria-valuemin={0}
aria-valuemax={100}
>
<div className="progress-bar" style={{ width: `${percent}%` }} />
</div>
</>
);
}Clamp the value, as the CRM dashboard does with Math.min(..., 100), so a quota above 100% does not overflow the track.
Labels, colors and stripes
Text inside .progress-bar appears on the bar itself. Keep it short, and only put it on bars that are wide enough to hold it. A bg- class changes the color, and the striped classes add stripes that stand still or move:
<div className="progress" role="progressbar" aria-label="Tasks done" aria-valuenow={25} aria-valuemin={0} aria-valuemax={100}>
<div className="progress-bar bg-success" style={{ width: "25%" }}>25%</div>
</div>
<div className="progress" role="progressbar" aria-label="Import" aria-valuenow={50} aria-valuemin={0} aria-valuemax={100}>
<div className="progress-bar progress-bar-striped" style={{ width: "50%" }} />
</div>
<div className="progress" role="progressbar" aria-label="Sync" aria-valuenow={75} aria-valuemin={0} aria-valuemax={100}>
<div className="progress-bar progress-bar-striped progress-bar-animated bg-info" style={{ width: "75%" }} />
</div>Stacked bars
When one bar has to show the parts of a whole, such as paid, pending and overdue amounts, stack the parts. Wrap one .progress per segment in .progress-stacked, and give each its own value and label:
const segments = [
{ label: "Paid", value: 45, color: "success" },
{ label: "Pending", value: 30, color: "warning" },
{ label: "Overdue", value: 10, color: "danger" },
];
<div className="progress-stacked">
{segments.map((segment) => (
<div
key={segment.label}
className="progress"
role="progressbar"
aria-label={segment.label}
aria-valuenow={segment.value}
aria-valuemin={0}
aria-valuemax={100}
style={{ width: `${segment.value}%` }}
>
<div className={`progress-bar bg-${segment.color}`} />
</div>
))}
</div>Accessibility
- Every bar needs a name:
aria-label, oraria-labelledbypointing at a visible label. - Keep
aria-valuenowequal to the width, from the same variable, so screen readers read the value the bar shows. - When the bar shows a value that is not a percentage, such as 18.4 GB, add
aria-valuetextwith that text. - A label on the bar must stay readable: AdminKit PRO gives
.progress-bar.bg-warningdark text, since white text does not reach a 4.5:1 contrast on it.
Related
- Next.js Bootstrap progress bar: the same markup in AdminKit for Next.js
- Bootstrap 5 progress: the progress bars of the HTML version
- Spinners: a loading state without a known value
- General UI demo
Last updated on
PopoversPro
A React Bootstrap popover with a title and body: opens on click next to its element, closes on Escape or a click outside, positioned by Floating UI.
SpinnersPro
React Bootstrap spinner markup in AdminKit PRO: border and grow spinners, colors and sizes, and a spinner shown from React state while data loads.