Components
- Accordion
- Alert
- Alert Dialog
- Aspect Ratio
- Attachment
- Avatar
- Badge
- Breadcrumb
- Bubble
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Collapsible
- Combobox
- Command
- Context Menu
- Date Picker
- Dialog
- Drawer
- Dropdown Menu
- Empty
- Field
- Hover Card
- Input
- Input OTP
- Input Group
- Item
- Kbd
- Label
- Marker
- Menubar
- Message
- Message Scroller
- Native Select
- Navigation Menu
- Pagination
- Popover
- Progress
- Radio Group
- Resizable
- Scroll Area
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Textarea
- Toggle
- Toggle Group
- Tooltip
- New Component
Elements
Charts
Icons
Uploading…0%
import { useEffect, useState } from "react";
import { Progress } from "@/components/ui/progress";
export const ProgressDemo = () => {
const [value, setValue] = useState(0);
useEffect(() => {
const timer = setTimeout(() => setValue(68), 300);
return () => clearTimeout(timer);
}, []);
return (
<div className="flex w-full max-w-sm flex-col gap-6">
{/* Animated on mount */}
<div className="flex flex-col gap-1.5">
<div className="flex justify-between text-sm">
<span className="text-muted-foreground">Uploading…</span>
<span className="font-medium">{value}%</span>
</div>
<Progress value={value} />
</div>
{/* Fixed values */}
<div className="flex flex-col gap-3">
<Progress value={0} />
<Progress value={25} />
<Progress value={50} />
<Progress value={75} />
<Progress value={100} />
</div>
{/* Thick */}
<Progress value={42} className="h-3" />
</div>
);
};With label
Pair with a label row above for a named progress indicator.
<div className="flex flex-col gap-1.5">
<div className="flex justify-between text-sm">
<span className="text-muted-foreground">Uploading…</span>
<span className="font-medium">68%</span>
</div>
<Progress value={68} />
</div>Animated value
Drive the value prop from state. The indicator transitions smoothly via transition-all.
"use client";
const [progress, setProgress] = useState(0);
useEffect(() => {
const timer = setTimeout(() => setProgress(68), 300);
return () => clearTimeout(timer);
}, []);
<Progress value={progress} />Indeterminate
Omit value (or pass null) to show an indeterminate state — Radix sets aria-valuenow to null and data-state="indeterminate".
<Progress />Custom height
Override h-2 (default) on the root.
<Progress value={60} className="h-1" /> {/* slim */}
<Progress value={60} className="h-3" /> {/* thick */}Custom colors
Target the root and indicator separately. The indicator inherits bg-primary — override on the root's [&>[data-slot=progress-indicator]] selector or apply inline style.
{/* Muted track, green fill */}
<Progress
value={80}
className="bg-green-100 dark:bg-green-950 [&>[data-slot=progress-indicator]]:bg-green-500"
/>Props
Progress
Extends all RadixProgress.Root props.
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | null | null | Current value (0–100). null = indeterminate |
max | number | 100 | Maximum value |
className | string | — | Applied to the track. Default height h-2 |
Usage
import { Progress } from "@/components/ui/progress";
<Progress value={60} />Specs
# Mint — Progress Specs
## Component
- name: progress
- file: registry/mint/progress.tsx
- installs to: components/ui/progress.tsx
- dependencies: radix-ui
- registryDependencies: none
## What is it
A horizontal bar that visualises the completion of a task or process. Use it
for file uploads, multi-step flows, or any operation with a measurable
percentage. Prefer Progress over a spinner when a numeric value is available;
omit `value` for indeterminate states where progress cannot be measured.
## Visual identity
Full-width, pill-shaped track (rounded-full) with a thin 8 px default height.
The track uses a 20 % opacity tint of --primary, giving a soft mint-green
contrast against the solid --primary indicator — fresh and vivid in Mint.
## Design tokens
--primary: oklch(0.5 0.14 155) / oklch(0.62 0.15 155) — indicator fill and track tint base
## Sub-components
- Progress → root track element (h-2, rounded-full, bg-primary/20, overflow-hidden)
- Indicator → inner fill bar (h-full, bg-primary, transition-all, translateX transform)
## States
- determinate: value 0–100 drives translateX(-${100 - value}%) on the indicator
- indeterminate: value=null → Radix sets data-state="indeterminate" and omits aria-valuenow; indicator rests at translateX(-100%) (hidden); no built-in animation — add a custom keyframe if a looping animation is needed
## Conventions
- Default height is h-2 (8 px); override on the root with h-1 (slim) or h-3 (thick) via className
- Override the indicator colour with [&>[data-slot=progress-indicator]]:bg-{color} on the root
- Always pair with a visible label or aria-label when used in isolation (Radix does not add one automatically)
- Sub-components expose data-slot="progress" and data-slot="progress-indicator" for CSS targeting
- value accepts 0–100; values outside that range are not clamped by the component — clamp in consuming codeInstallation
$ npx shadcn add \https://gin-design.vercel.app/progress