Progress Bar

A horizontal progress indicator that visualizes completion as a percentage. Supports a smooth default mode and a stepped mode that snaps to discrete intervals.

import { ProgressBar } from "@tenstorrent/vesper/progress-bar";

export default function ProgressBarDemo() {
  return <ProgressBar value={65} />;
}

Options

PropTypeDescriptionDefault
valuenumberThe progress value from 0 to 100.—
size"sm" | "md" | "lg"The rendered size of the progress bar."md"
variant"default" | "steps""default" renders a smooth indicator. "steps" clamps the width to the nearest tick value."default"
stepsnumberThe number of segments when variant is "steps". Must be an integer greater than 0.10
stepRoundingStrategy(n: number) => numberDetermines how to clamp progress to the nearest tick value.Math.round
animatedbooleanWhether to animate progress bar value changes.false

All other props are forwarded to the wrapping <div> element.

A ProgressBar is announced with an aria-label of "Progress" by default. Pass your own aria-label when a page renders more than one, so that each is announced with what it is tracking.

Examples

Basic usage

Render a ProgressBar by giving it a numeric value prop from 0 to 100:

import { ProgressBar } from "@tenstorrent/vesper/progress-bar";

export default function BasicProgressBar() {
  return <ProgressBar value={50} />;
}

Different sizes

A ProgressBar can be rendered in one of three sizes, "sm", "md", or "lg". The default size is "md":

import { ProgressBar } from "@tenstorrent/vesper/progress-bar";

export default function ProgressBarSizes() {
  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        gap: "var(--vesper-spacing-4)",
      }}
    >
      <ProgressBar aria-label="A small progress bar" value={41} size="sm" />
      <ProgressBar aria-label="A medium progress bar" value={17} size="md" />
      <ProgressBar aria-label="A large progress bar" value={88} size="lg" />
    </div>
  );
}

Rendering step intervals

A ProgressBar can be rendered in one of two variants, "default" or "steps". The default variant is "default", which renders a ProgressBar with no step intervals. To render a ProgressBar with step intervals, use the "steps" variant:

import { ProgressBar } from "@tenstorrent/vesper/progress-bar";

export default function SteppedProgressBar() {
  return <ProgressBar value={30} variant="steps" />;
}

A "steps" variant ProgressBar will visually snap the progress indicator to the nearest interval, using Math.round by default. To adjust how step-rounding is calculated, you can pass a custom rounding function to the component via the stepRoundingStrategy prop:

import { ProgressBar } from "@tenstorrent/vesper/progress-bar";

export default function StepRoundingStrategies() {
  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        gap: "var(--vesper-spacing-4)",
      }}
    >
      {/* rounds with `Math.ceil` instead of `Math.round` */}
      <ProgressBar
        aria-label="Progress rounded up"
        value={73}
        variant="steps"
        stepRoundingStrategy={Math.ceil}
      />
      {/* rounds with `Math.floor` instead of `Math.round` */}
      <ProgressBar
        aria-label="Progress rounded down"
        value={73}
        variant="steps"
        stepRoundingStrategy={Math.floor}
      />
    </div>
  );
}

By default, when rendering a stepped ProgressBar, it will render with 10 steps. To modify the number of steps rendered, pass any positive integer value to the steps prop:

import { ProgressBar } from "@tenstorrent/vesper/progress-bar";

export default function FiveStepProgressBar() {
  return <ProgressBar value={27} variant="steps" steps={5} />;
}

Animating progress

To animate a ProgressBar as its value changes, you can pass animated={true} or just animated as a prop:

Current value: 66

import { useState } from "react";

import { Button } from "@tenstorrent/vesper/button";
import { ProgressBar } from "@tenstorrent/vesper/progress-bar";
import { Typography } from "@tenstorrent/vesper/typography";

export default function AnimatedProgressBars() {
  const [value, setValue] = useState(66);

  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        gap: "var(--vesper-spacing-4)",
      }}
    >
      <ProgressBar aria-label="Default progress bar" value={value} animated />
      <ProgressBar
        aria-label="Stepped progress bar"
        value={value}
        variant="steps"
        animated
      />
      <Button
        size="sm"
        onClick={() => setValue(Math.round(Math.random() * 100))}
      >
        Change value
      </Button>
      <Typography variant="copy-sm">Current value: {value}</Typography>
    </div>
  );
}