Progress

free

Progress shows how far a task or value has advanced, as a line or a circular gauge.

Preview
Dark
Storage used62 GB of 100 GB
62%
import Progress from '@/components/ui/Progress';

export default function UsageDemo() {
  return (
    <div className="w-full max-w-sm rounded-card border border-border bg-card p-4 shadow-card">
      <div className="flex items-center justify-between">
        <span className="text-sm font-semibold text-foreground">
          Storage used
        </span>
        <span className="text-xs text-muted-foreground">62 GB of 100 GB</span>
      </div>
      <div className="mt-4">
        <Progress percent={62} />
      </div>
    </div>
  );
}

Installation

Add this component with the NateUI CLI.

npx nateui@latest add Progress

Examples

Basic

Preview
Dark
45%
import Progress from '@/components/ui/Progress';

export default function BasicDemo() {
  return (
    <div className="w-full max-w-sm">
      <Progress percent={45} />
    </div>
  );
}

Circle

Preview
Dark
80%
import Progress from '@/components/ui/Progress';

export default function CircleDemo() {
  return (
    <Progress variant="circle" percent={80} />
  );
}

Size

Preview
Dark
50%
50%
import Progress from '@/components/ui/Progress';

export default function SizeDemo() {
  return (
    <div className="flex flex-col gap-8">
      <Progress size="md" percent={50} />
      <Progress variant="circle" percent={50} width={80} />
    </div>
  );
}

Color

Preview
Dark
38%
74%
92%
import Progress from '@/components/ui/Progress';

export default function ColorDemo() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-4">
      <Progress strokeClass="bg-destructive" percent={38} />
      <Progress strokeClass="bg-warning" percent={74} />
      <Progress strokeClass="bg-success" percent={92} />
    </div>
  );
}

Custom Info

Preview
Dark
68%
completed
import { PiCheckCircle, PiWarning } from 'react-icons/pi'
import Progress from '@/components/ui/Progress';

export default function CustomInfoDemo() {
  return (
    <div className="flex flex-wrap items-center gap-8">
      <div className="flex w-full max-w-xs flex-col gap-4">
        <Progress
          strokeClass="bg-success"
          percent={100}
          customInfo={<PiCheckCircle className="text-lg text-success" />}
        />
        <Progress
          strokeClass="bg-warning"
          percent={70}
          customInfo={<PiWarning className="text-lg text-warning" />}
        />
        <Progress percent={40} showInfo={false} />
      </div>
      <div className="flex justify-center items-center">
        <Progress
          variant="circle"
          percent={68}
          width={140}
          customInfo={
            <div className="text-center">
              <div className="text-xl font-semibold text-foreground">68%</div>
              <div className="text-xs text-muted-foreground">completed</div>
            </div>
          }
        />
      </div>
    </div>
  );
}

Gap

Preview
Dark
75%
import Progress from '@/components/ui/Progress';

export default function GapDemo() {
  return (
    <Progress
      variant="circle"
      percent={75}
      gapDegree={70}
      gapPosition="bottom"
      strokeWidth={8}
    />
  );
}

Controlled

Preview
Dark
40%
40%
import { useState } from 'react';
import { PiMinus, PiPlus } from 'react-icons/pi'
import Button from '@/components/ui/Button';
import Progress from '@/components/ui/Progress';

export default function ControlledDemo() {
  const [percent, setPercent] = useState(40);

  const step = (amount: number) => {
    setPercent((current) => Math.min(100, Math.max(0, current + amount)));
  };

  return (
    <div className="flex w-full max-w-sm flex-col gap-4">
      <div className="flex items-center gap-8">
        <Progress percent={percent} />
        <Progress variant="circle" percent={percent} width={80} />
      </div>
      <div className="flex items-center gap-2">
        <Button
          shape="circle"
          size="sm"
          icon={<PiMinus />}
          disabled={percent === 0}
          onClick={() => step(-10)}
        />
        <Button
          shape="circle"
          size="sm"
          icon={<PiPlus />}
          disabled={percent === 100}
          onClick={() => step(10)}
        />
      </div>
    </div>
  );
}

API

Progress renders a line or circle indicator driven by percent. The line variant grows a bar and places its label beside it; the circle variant draws a gauge and centers its label. size applies to the line; width, gapDegree, gapPosition, strokeWidth, and strokeLinecap shape the circle.

PropDescriptionTypeDefault
variantIndicator shape to render.'line' | 'circle''line'
percentCompletion value from 0 to 100.number0
showInfoWhether the percentage label is shown.booleantrue
customInfoReplaces the default ${percent}% label.string | ReactNode-
sizeLine thickness. Applies to the line variant only.'sm' | 'md''md'
strokeClassClass applied to the filled indicator. Defaults to the primary color.string-
trailClassClass applied to the unfilled track.string-
widthDiameter of the circle, in pixels or a CSS size. Circle only.string | number120
gapDegreeSize of the gap in the circle ring, in degrees (0–360). Circle only.number0
gapPositionWhere the ring gap sits. Circle only.GapPosition'top'
strokeWidthThickness of the circle ring stroke. Circle only.number6
strokeLinecapShape of the circle stroke ends. Circle only.StrokeLinecap'round'
classNameClass names applied to the progress root.string-
refRef forwarded to the root element.Ref<HTMLDivElement>-
...nativePropsNative div props applied to the root element.ComponentProps<'div'>-

Types

type GapPosition = 'top' | 'right' | 'bottom' | 'left';
type StrokeLinecap = 'round' | 'square';