Progress Circle
0%
The ProgressCircle
component displays a circular progress indicator, commonly used to show file upload progress. It visually represents a percentage value (0-100) with a ring and a centered text label.
tip
If you are installing the other dropzone components via the CLI, this component will be installed automatically. You can skip the following steps.
Installation
- CLI
- Manual
- pnpm
- npm
- yarn
- bun
bash
pnpm dlx shadcn@latest add https://edgestore.dev/r/progress-circle.json
bash
npx shadcn@latest add https://edgestore.dev/r/progress-circle.json
bash
npx shadcn@latest add https://edgestore.dev/r/progress-circle.json
shell
bunx --bun shadcn@latest add https://edgestore.dev/r/progress-circle.json
Setup for manual installation
First you will need to add the cn helper following the manual install setup guide.
Copy this component
tsx
import { cn } from '@/lib/utils';import * as React from 'react';/*** Props for the ProgressCircle component.** @interface ProgressCircleProps* @extends {React.HTMLAttributes<HTMLDivElement>}*/export interface ProgressCirclePropsextends React.HTMLAttributes<HTMLDivElement> {/*** The progress value as a percentage (0-100).*/progress: number;/*** The diameter of the circle in pixels.* @default 48*/size?: number;/*** The width of the progress stroke in pixels.* @default 4*/strokeWidth?: number;}/*** A circular progress indicator component that visualizes completion percentage.** @component* @example* ```tsx* <ProgressCircle progress={75} />* <ProgressCircle progress={50} size={64} strokeWidth={6} />* ```*/const ProgressCircle = React.forwardRef<HTMLDivElement, ProgressCircleProps>(({ progress, size = 48, strokeWidth = 4, className, ...props }, ref) => {const radius = (size - strokeWidth) / 2;const circumference = 2 * Math.PI * radius;const offset = circumference - (progress / 100) * circumference;return (<divref={ref}className={cn('relative flex flex-col items-center justify-center text-white dark:text-gray-100',className,)}style={{width: size,height: size,}}{...props}><svgclassName="absolute" // Position SVG centered relative to the divwidth={size}height={size}viewBox={`0 0 ${size} ${size}`}style={{ transform: 'rotate(-90deg)' }} // Start from top>{/* Background track */}<circlecx={size / 2}cy={size / 2}r={radius}strokeWidth={strokeWidth}className="fill-none stroke-gray-500 dark:stroke-gray-600"/>{/* Progress arc */}<circlecx={size / 2}cy={size / 2}r={radius}strokeWidth={strokeWidth}className="fill-none stroke-white dark:stroke-gray-200"strokeDasharray={circumference}strokeDashoffset={offset}style={{ transition: 'stroke-dashoffset 0.3s ease' }} // Smooth transition/></svg>{/* Progress Percentage Text (centered visually) */}<div className="z-10 text-xs font-medium">{Math.round(progress)}%</div></div>);},);ProgressCircle.displayName = 'ProgressCircle';export { ProgressCircle };
Usage
Import the component and provide the progress
prop. You can optionally customize the size
and strokeWidth
.
tsx
import { ProgressCircle } from '@/components/ui/progress-circle';function ProgressDemo() {const progress = 75;return (<div className="flex items-center space-x-4 p-4 bg-gray-800 rounded-lg">{/* Default size */}<ProgressCircle progress={progress} />{/* Larger size with thicker stroke */}<ProgressCircle progress={progress} size={64} strokeWidth={6} />{/* Smaller size */}<ProgressCircle progress={progress} size={32} strokeWidth={3} /></div>);}