The Progress component displays a horizontal progress bar that can be used to show task completion, loading states, or any measured progress.
Installation
npx shadcn@latest add @eo-n/progress
Install dependencies
npm install @base-ui/react
Copy component code
Copy and paste the following code into your project at components/ui/progress.tsx:"use client";
import * as React from "react";
import { Progress as ProgressPrimitive } from "@base-ui/react";
import { cn } from "@/lib/utils";
function Progress({
className,
children,
...props
}: React.ComponentProps<typeof ProgressPrimitive.Root>) {
return (
<ProgressPrimitive.Root
data-slot="progress"
className={cn(
"relative grid grid-cols-1 gap-1 overflow-hidden has-data-[slot='progress-label']:grid-cols-2",
className
)}
{...props}
>
{children}
<ProgressPrimitive.Track
data-slot="progress-track"
className="bg-secondary col-span-full block h-2 w-full overflow-hidden rounded-full"
>
<ProgressPrimitive.Indicator
data-slot="progress-indicator"
className="bg-primary block transition-all duration-500"
/>
</ProgressPrimitive.Track>
</ProgressPrimitive.Root>
);
}
function ProgressLabel({
className,
...props
}: React.ComponentProps<typeof ProgressPrimitive.Label>) {
return (
<ProgressPrimitive.Label
data-slot="progress-label"
className={cn("text-foreground text-sm font-medium", className)}
{...props}
/>
);
}
function ProgressValue({
className,
...props
}: React.ComponentProps<typeof ProgressPrimitive.Value>) {
return (
<ProgressPrimitive.Value
data-slot="progress-value"
className={cn(
"text-foreground text-right text-sm font-medium",
className
)}
{...props}
/>
);
}
export { Progress, ProgressValue, ProgressLabel };
Update imports
Update the import paths to match your project setup.
import { Progress } from "@/components/ui/progress";
Examples
Basic Progress
import { Progress } from "@/components/ui/progress";
export default function Example() {
const [value, setValue] = React.useState(0);
React.useEffect(() => {
const interval = setInterval(() => {
setValue((current) => Math.min(100, current + 10));
}, 500);
return () => clearInterval(interval);
}, []);
return <Progress value={value} className="w-80" />;
}
With Label
import { Progress, ProgressLabel } from "@/components/ui/progress";
<Progress value={45}>
<ProgressLabel>Uploading...</ProgressLabel>
</Progress>
With Value Display
import { Progress, ProgressLabel, ProgressValue } from "@/components/ui/progress";
<Progress value={67}>
<ProgressLabel>Installation Progress</ProgressLabel>
<ProgressValue />
</Progress>
Controlled Progress
import { useState, useEffect } from "react";
import { Progress, ProgressLabel, ProgressValue } from "@/components/ui/progress";
export default function ControlledProgress() {
const [progress, setProgress] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
setProgress((prev) => {
if (prev >= 100) {
clearInterval(timer);
return 100;
}
return prev + 5;
});
}, 200);
return () => clearInterval(timer);
}, []);
return (
<Progress value={progress}>
<ProgressLabel>Processing</ProgressLabel>
<ProgressValue />
</Progress>
);
}
Indeterminate State
<Progress value={null}>
<ProgressLabel>Loading...</ProgressLabel>
</Progress>
Component API
Progress
The root container component.
The current progress value (0-100). Pass null for an indeterminate state.
The maximum value. Defaults to 100.
Additional CSS classes to apply to the root element.
Optional label and value components.
ProgressLabel
Displays a label for the progress bar.
ProgressValue
Displays the current progress value as text.
format
(value: number, max: number) => string
Custom formatter for the value display. Defaults to showing percentage.
Accessibility
The Progress component is built on Base UI and includes:
- Proper ARIA attributes (
role="progressbar", aria-valuenow, aria-valuemin, aria-valuemax)
- Screen reader announcements for value changes
- Support for indeterminate states
Reference
Built on top of Base UI Progress.