"use client";
import * as React from "react";
import { Progress } from "@/components/ui/progress";
export function ProgressDemo() { const [progress, setProgress] = React.useState(13);
React.useEffect(() => { const timer = setTimeout(() => setProgress(66), 500); return () => clearTimeout(timer); }, []);
return <Progress value={progress} className="w-[60%]" />;}pnpm dlx shadcn@latest add @herocn/progressimport { Progress, ProgressLabel, ProgressValue,} from "@/components/ui/progress"<Progress value={33} />Use ProgressLabel and ProgressValue as optional children for a header row; the track and indicator are rendered automatically inside Progress.
Progress├── ProgressLabel├── ProgressValue└── ProgressTrack └── ProgressIndicatorUse ProgressLabel and ProgressValue to show a title and formatted percentage.
import { Progress, ProgressLabel, ProgressValue,} from "@/components/ui/progress";
export function ProgressLabelExample() { return ( <Progress value={56} className="w-full max-w-sm"> <ProgressLabel>Upload progress</ProgressLabel> <ProgressValue /> </Progress> );}Use the variant prop to match semantic status colors (default uses the neutral foreground on the track).
Default
Primary
Success
Warning
Destructive
import { Progress } from "@/components/ui/progress";
export function ProgressVariants() { return ( <div className="flex w-full max-w-sm flex-col gap-4"> <div className="space-y-1"> <p className="text-muted-foreground text-xs">Default</p> <Progress value={45} variant="default" className="w-full" /> </div> <div className="space-y-1"> <p className="text-muted-foreground text-xs">Primary</p> <Progress value={50} variant="primary" className="w-full" /> </div> <div className="space-y-1"> <p className="text-muted-foreground text-xs">Success</p> <Progress value={72} variant="success" className="w-full" /> </div> <div className="space-y-1"> <p className="text-muted-foreground text-xs">Warning</p> <Progress value={38} variant="warning" className="w-full" /> </div> <div className="space-y-1"> <p className="text-muted-foreground text-xs">Destructive</p> <Progress value={88} variant="destructive" className="w-full" /> </div> </div> );}Use the size prop to change the track height (sm, default, or lg).
import { Progress, ProgressLabel, ProgressValue,} from "@/components/ui/progress";
export function ProgressSizes() { return ( <div className="flex w-full max-w-sm flex-col gap-6"> <Progress value={40} size="sm" className="w-full"> <ProgressLabel>Small</ProgressLabel> <ProgressValue /> </Progress> <Progress value={55} size="default" className="w-full"> <ProgressLabel>Default</ProgressLabel> <ProgressValue /> </Progress> <Progress value={70} size="lg" className="w-full"> <ProgressLabel>Large</ProgressLabel> <ProgressValue /> </Progress> </div> );}Drive the bar from another control, such as a slider.
"use client";
import * as React from "react";
import { Progress } from "@/registry/new-york-v4//ui/progress";import { Slider } from "@/registry/new-york-v4//ui/slider";
export function ProgressControlled() { const [value, setValue] = React.useState(50);
return ( <div className="flex w-full max-w-sm flex-col gap-4"> <Progress size="lg" value={value} className="w-full" /> <Slider value={value} onValueChange={(value) => setValue(value as number)} min={0} max={100} step={1} /> </div> );}To enable RTL support in shadcn/ui, see the RTL configuration guide.
"use client";
import { type Translations, useTranslation,} from "@/components/language-selector";import { Progress, ProgressLabel, ProgressValue,} from "@/components/ui/progress";
const translations: Translations = { en: { dir: "ltr", values: { label: "Upload progress", }, }, ar: { dir: "rtl", values: { label: "تقدم الرفع", }, }, he: { dir: "rtl", values: { label: "התקדמות העלאה", }, },};
function toArabicNumerals(num: number): string { const arabicNumerals = ["٠", "١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩"]; return num .toString() .split("") .map((digit) => arabicNumerals[Number.parseInt(digit, 10)] ?? digit) .join("");}
export function ProgressRtl() { const { dir, t, language } = useTranslation(translations, "ar");
const formatNumber = (num: number): string => { if (language === "ar") { return toArabicNumerals(num); } return num.toString(); };
return ( <div className="w-full max-w-sm" lang={language} dir={dir}> <Progress value={56} className="w-full"> <ProgressLabel>{t.label}</ProgressLabel> <ProgressValue> {(_formatted, value) => ( <span className="ms-auto">{formatNumber(value ?? 0)}%</span> )} </ProgressValue> </Progress> </div> );}Progress wraps Base UI Progress.Root and sets variant and size on the root for styling the built-in track and indicator.
| Prop | Type | Default |
|---|---|---|
| variant | "default" | "primary" | "success" | "warning" | "destructive" | "primary" |
Semantic color of the filled portion of the bar. | ||
| size | "sm" | "default" | "lg" | "default" |
Height of the track. | ||
| value | number | null | — |
Current value between min and max. Use null for an indeterminate bar. | ||
| min | number | 0 |
Minimum value (inherited from Base UI Progress root). | ||
| max | number | 100 |
Maximum value (inherited from Base UI Progress root). | ||
| format | Intl.NumberFormatOptions | — |
Options passed to Intl when formatting the displayed value. | ||
| className | string | — |
Additional classes on the root element. | ||
| children | React.ReactNode | — |
Typically `ProgressLabel` and/or `ProgressValue`. | ||
| Prop | Type | Default |
|---|---|---|
| className | string | — |
Additional classes for the label. | ||
| Prop | Type | Default |
|---|---|---|
| className | string | — |
Additional classes for the value text. | ||
| children | (formattedValue: string | null, value: number | null) => React.ReactNode | — |
Optional render function to customize how the numeric value is shown. | ||
These parts are rendered by default. They are exported if you need to build a fully custom layout alongside the same primitives.
For the full root API (locale, getAriaValueText, etc.), see the Base UI Progress documentation.