Progress
Component
Refined Tailwind progress bar components and Tailwind CSS loading indicators displaying operation status with smooth animations.
Install via CLI
Run this command to automatically add the component and its dependencies to your project.
npx @abhaysinghr516/business-wish add progressNew to the CLI? Run
npx @abhaysinghr516/business-wish init first to initialize your project.Keeping users informed during long tasks is paramount to a premium experience. A sleek Tailwind progress bar provides immediate, clear feedback. This collection of Tailwind CSS loading indicators includes animated gradients, floating percentage labels, and beautiful circular SVGs.
Use a progress bar alongside a File Upload zone to indicate transfer status, or swap it out for an indeterminate Loader when you cannot calculate the exact duration.
Sleek Basic Progress
import React, { useState, useEffect } from "react";
const BasicProgress = () => {
const [progress, setProgress] = useState(0);
useEffect(() => {
const timer = setTimeout(() => setProgress(65), 500);
return () => clearTimeout(timer);
}, []);
return (
<div className="w-full max-w-md mx-auto my-8">
<div className="h-1.5 w-full bg-neutral-100 dark:bg-neutral-800 rounded-full overflow-hidden">
<div
className="h-full bg-neutral-900 dark:bg-white rounded-full transition-all duration-1000 ease-out"
style={{ width: `${progress}%` }}
/>
</div>
</div>
);
};
export default BasicProgress;
Progress with Floating Label
import React, { useState, useEffect } from "react";
const ProgressWithLabel = () => {
const [progress, setProgress] = useState(0);
useEffect(() => {
const timer = setTimeout(() => setProgress(82), 500);
return () => clearTimeout(timer);
}, []);
return (
<div className="w-full max-w-md mx-auto my-8 mt-12">
<div className="relative h-2 w-full bg-neutral-100 dark:bg-neutral-800 rounded-full">
<div
className="absolute top-0 left-0 h-full bg-blue-500 rounded-full transition-all duration-1000 ease-out"
style={{ width: `${progress}%` }}
>
<div className="absolute -top-8 right-0 translate-x-1/2">
<span className="bg-neutral-900 dark:bg-white text-white dark:text-neutral-900 text-[11px] font-bold px-2 py-1 rounded-md shadow-sm">
{progress}%
</span>
<div className="w-2 h-2 bg-neutral-900 dark:bg-white rotate-45 absolute -bottom-1 left-1/2 -translate-x-1/2" />
</div>
</div>
</div>
</div>
);
};
export default ProgressWithLabel;
Animated Gradient Progress
import React, { useState, useEffect } from "react";
const AnimatedProgress = () => {
const [progress, setProgress] = useState(0);
useEffect(() => {
const timer = setTimeout(() => setProgress(100), 500);
return () => clearTimeout(timer);
}, []);
return (
<div className="w-full max-w-md mx-auto my-8">
<div className="flex justify-between items-end mb-2">
<span className="text-[13px] font-medium text-neutral-600 dark:text-neutral-400">Uploading files...</span>
<span className="text-[13px] font-semibold text-neutral-900 dark:text-white">{progress}%</span>
</div>
<div className="h-2 w-full bg-neutral-100 dark:bg-neutral-800 rounded-full overflow-hidden relative">
<div
className="absolute top-0 left-0 h-full rounded-full transition-all duration-1000 ease-out bg-gradient-to-r from-blue-500 via-indigo-500 to-purple-500"
style={{ width: `${progress}%` }}
>
{/* Animated shimmer overlay */}
<div className="absolute inset-0 w-full h-full bg-gradient-to-r from-transparent via-white/30 to-transparent -translate-x-full animate-[shimmer_2s_infinite]" />
</div>
</div>
<style>{`
@keyframes shimmer {
100% { transform: translateX(100%); }
}
`}</style>
</div>
);
};
export default AnimatedProgress;
Circular Progress Indicator
import React, { useState, useEffect } from "react";
const CircularProgress = () => {
const [progress, setProgress] = useState(0);
const size = 120;
const strokeWidth = 8;
const radius = (size - strokeWidth) / 2;
const circumference = radius * 2 * Math.PI;
const offset = circumference - (progress / 100) * circumference;
useEffect(() => {
const timer = setTimeout(() => setProgress(75), 500);
return () => clearTimeout(timer);
}, []);
return (
<div className="flex items-center justify-center my-8">
<div className="relative" style={{ width: size, height: size }}>
{/* Background Circle */}
<svg className="w-full h-full -rotate-90" viewBox={`0 0 ${size} ${size}`}>
<circle
className="text-neutral-100 dark:text-neutral-800"
strokeWidth={strokeWidth}
stroke="currentColor"
fill="transparent"
r={radius}
cx={size / 2}
cy={size / 2}
/>
{/* Progress Circle */}
<circle
className="text-neutral-900 dark:text-white transition-all duration-1000 ease-out"
strokeWidth={strokeWidth}
strokeDasharray={circumference}
strokeDashoffset={offset}
strokeLinecap="round"
stroke="currentColor"
fill="transparent"
r={radius}
cx={size / 2}
cy={size / 2}
/>
</svg>
{/* Center Text */}
<div className="absolute inset-0 flex flex-col items-center justify-center">
<span className="text-3xl font-semibold text-neutral-900 dark:text-white tracking-tighter">
{progress}<span className="text-lg text-neutral-400">%</span>
</span>
</div>
</div>
</div>
);
};
export default CircularProgress;
Segments Progress
import React, { useState, useEffect } from "react";
const SegmentsProgress = () => {
const [currentStep, setCurrentStep] = useState(0);
const totalSteps = 4;
useEffect(() => {
const timer = setTimeout(() => setCurrentStep(2), 500);
return () => clearTimeout(timer);
}, []);
return (
<div className="w-full max-w-md mx-auto my-8">
<div className="flex justify-between items-end mb-3">
<span className="text-[13px] font-medium text-neutral-600 dark:text-neutral-400">Account Setup</span>
<span className="text-[13px] font-semibold text-neutral-900 dark:text-white">Step {currentStep + 1} of {totalSteps}</span>
</div>
<div className="flex items-center justify-between gap-2">
{[...Array(totalSteps)].map((_, i) => (
<div key={i} className="h-1.5 w-full bg-neutral-100 dark:bg-neutral-800 rounded-full overflow-hidden">
<div
className={`h-full rounded-full transition-all duration-500 ease-out ${
i <= currentStep ? "bg-neutral-900 dark:bg-white w-full" : "w-0"
}`}
/>
</div>
))}
</div>
</div>
);
};
export default SegmentsProgress;
Indeterminate Progress
import React from "react";
const IndeterminateProgress = () => {
return (
<div className="w-full max-w-md mx-auto my-8">
<div className="h-1 w-full bg-neutral-100 dark:bg-neutral-800 overflow-hidden relative rounded-full">
<div className="absolute top-0 h-full bg-neutral-900 dark:bg-white w-1/3 rounded-full animate-[indeterminate_1.5s_infinite_ease-in-out]" />
</div>
<style>{`
@keyframes indeterminate {
0% { left: -35%; right: 100%; }
60% { left: 100%; right: -90%; }
100% { left: 100%; right: -90%; }
}
`}</style>
</div>
);
};
export default IndeterminateProgress;