AdminKitDocs
Components

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.

Pro

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

ClassEffect
progressThe track, 1rem high; it carries role="progressbar" and the aria-value* attributes
progress-barThe filled part; its width is the value
progress-sm, progress-lgAdminKit: a 0.4rem or 1.5rem high track
bg-<color>The bar color: bg-success, bg-warning, ...
progress-bar-stripedStripes over the bar color
progress-bar-animatedMoves the stripes
progress-stackedHolds 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, or aria-labelledby pointing at a visible label.
  • Keep aria-valuenow equal 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-valuetext with that text.
  • A label on the bar must stay readable: AdminKit PRO gives .progress-bar.bg-warning dark text, since white text does not reach a 4.5:1 contrast on it.

Last updated on

On this page