Progress Indicators
Visual feedback components for indicating loading states, progress completion, and ongoing processes. Includes progress bars, spinners, skeleton loaders, and interactive progress displays for enhanced user experience.
Quick Navigation
Progress Bars
Linear progress indicators showing completion percentage or task progress. Available in different sizes, colors, and with optional labels.
Basic Progress Bars
Progress Bar Sizes
Animated Progress Bars
Spinners
Rotating loading indicators for indefinite loading states. Available in different sizes and colors to match your design needs.
Basic Spinners
Spinner Sizes
Spinner Variations
Skeleton Loaders
Placeholder content that mimics the structure of loaded content, providing users with a sense of progress while content loads.
Basic Skeleton Elements
Text Lines
Avatar
Image Placeholder
Button
Complex Skeleton Layouts
User Card
Article Preview
Table Row
Loading States
Complete loading state examples for common UI patterns including buttons, forms, and page overlays.
Loading Buttons
Loading Forms
Page Loading Overlay
Demo Content
This is some demo content that will be covered by the loading overlay when activated.
Step Progress
Multi-step progress indicators for wizards, forms, and guided processes. Shows current step, completed steps, and remaining steps.
Horizontal Step Progress
Vertical Step Progress
Circular Progress
Circular progress indicators for showing completion percentage in a compact format. Ideal for dashboards and status displays.
Basic Circular Progress
Interactive Circular Progress
Usage Guidelines
When to Use Progress Indicators
- File uploads: Show upload progress with percentage and estimated time remaining
- Form submission: Indicate processing state during form submission
- Page loading: Use skeleton loaders for content that takes time to load
- Multi-step processes: Show current step and overall progress in wizards
- Task completion: Display project or task completion percentage
- Data processing: Indicate system operations that take time
Best Practices
- Appropriate timing: Show progress indicators for operations taking longer than 1 second
- Clear messaging: Provide context about what's happening during loading
- Realistic progress: Ensure progress bars reflect actual completion status
- Consistent placement: Position loading indicators in predictable locations
- Smooth animations: Use fluid transitions to avoid jarring visual changes
- Graceful degradation: Handle errors gracefully and provide recovery options
Accessibility Requirements
-
ARIA attributes: Use
role="progressbar",aria-valuenow, andaria-valuetext - Screen reader support: Provide text alternatives for visual progress indicators
- Loading announcements: Announce loading states and completion to screen readers
- Focus management: Maintain logical focus flow during loading states
- Color independence: Don't rely solely on color to convey progress state
- Motion preferences: Respect user preferences for reduced motion
Performance Considerations
- CSS animations: Prefer CSS animations over JavaScript for better performance
- Hardware acceleration: Use transform and opacity for smooth animations
- Debounce updates: Limit progress update frequency to avoid overwhelming the UI
- Skeleton efficiency: Use simple shapes and avoid complex skeleton layouts
- Memory management: Clean up intervals and timeouts when components unmount
CSS Classes Reference
/* Progress Bars */
.progress-bar {
@apply w-full bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden;
height: 8px;
}
.progress-bar.progress-sm {
height: 4px;
}
.progress-bar.progress-lg {
height: 12px;
}
.progress-fill {
@apply h-full bg-blue-500 rounded-full transition-all duration-300 ease-out;
}
.progress-fill.progress-success {
@apply bg-green-500;
}
.progress-fill.progress-warning {
@apply bg-yellow-500;
}
.progress-fill.progress-danger {
@apply bg-red-500;
}
.progress-fill.progress-animated {
@apply transition-all duration-500 ease-out;
}
.progress-fill.progress-indeterminate {
@apply bg-blue-500;
animation: indeterminate 2s infinite ease-in-out;
}
@keyframes indeterminate {
0% { transform: translateX(-100%); }
50% { transform: translateX(0%); }
100% { transform: translateX(100%); }
}
/* Spinners */
.spinner {
@apply w-6 h-6 border-2 border-gray-300 border-t-blue-500 rounded-full;
animation: spin 1s linear infinite;
}
.spinner-xs { @apply w-3 h-3 border; }
.spinner-sm { @apply w-4 h-4; }
.spinner-lg { @apply w-8 h-8 border-4; }
.spinner-xl { @apply w-12 h-12 border-4; }
.spinner-primary { @apply border-t-blue-500; }
.spinner-success { @apply border-t-green-500; }
.spinner-warning { @apply border-t-yellow-500; }
.spinner-danger { @apply border-t-red-500; }
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* Spinner Variations */
.spinner-dots {
@apply flex space-x-1;
}
.spinner-dots div {
@apply w-2 h-2 bg-blue-500 rounded-full;
animation: dots 1.4s ease-in-out infinite both;
}
.spinner-dots div:nth-child(1) { animation-delay: -0.32s; }
.spinner-dots div:nth-child(2) { animation-delay: -0.16s; }
@keyframes dots {
0%, 80%, 100% { transform: scale(0); }
40% { transform: scale(1); }
}
.spinner-pulse {
@apply w-6 h-6 bg-blue-500 rounded-full;
animation: pulse 2s infinite;
}
.spinner-ring {
@apply w-6 h-6 border-2 border-blue-200 rounded-full;
border-top-color: theme('colors.blue.500');
animation: spin 1s linear infinite;
}
.spinner-bars {
@apply flex space-x-1;
}
.spinner-bars div {
@apply w-1 h-4 bg-blue-500;
animation: bars 1.2s infinite ease-in-out;
}
.spinner-bars div:nth-child(1) { animation-delay: -1.1s; }
.spinner-bars div:nth-child(2) { animation-delay: -1.0s; }
.spinner-bars div:nth-child(3) { animation-delay: -0.9s; }
.spinner-bars div:nth-child(4) { animation-delay: -0.8s; }
@keyframes bars {
0%, 40%, 100% { transform: scaleY(0.4); }
20% { transform: scaleY(1.0); }
}
/* Skeleton Loaders */
.skeleton {
@apply bg-gray-200 dark:bg-gray-700 rounded;
animation: skeleton 1.5s ease-in-out infinite alternate;
}
.skeleton-text {
@apply h-4 w-full;
}
.skeleton-avatar {
@apply w-10 h-10 rounded-full;
}
.skeleton-image {
@apply w-full h-48;
}
.skeleton-button {
@apply h-10 w-24 rounded;
}
.skeleton-input {
@apply h-10 w-full rounded;
}
.skeleton-card {
@apply bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-4;
}
@keyframes skeleton {
0% { opacity: 1; }
100% { opacity: 0.4; }
}
/* Step Progress */
.step-progress {
@apply flex items-start space-x-0;
}
.step-item {
@apply flex flex-col items-center flex-1 relative;
}
.step-marker {
@apply w-10 h-10 rounded-full border-2 flex items-center justify-center;
@apply text-sm font-medium bg-white dark:bg-gray-800;
@apply border-gray-300 dark:border-gray-600 text-gray-500 dark:text-gray-400;
}
.step-item.completed .step-marker {
@apply bg-blue-500 border-blue-500 text-white;
}
.step-item.active .step-marker {
@apply border-blue-500 text-blue-500;
}
.step-content {
@apply text-center mt-2;
}
.step-title {
@apply text-sm font-medium text-gray-900 dark:text-white;
}
.step-description {
@apply text-xs text-gray-500 dark:text-gray-400 mt-1;
}
.step-connector {
@apply absolute top-5 left-1/2 w-full h-0.5 bg-gray-300 dark:bg-gray-600;
@apply transform -translate-y-1/2 -z-10;
}
.step-connector.completed {
@apply bg-blue-500;
}
/* Vertical Step Progress */
.step-progress-vertical {
@apply space-y-6;
}
.step-item-vertical {
@apply flex items-start space-x-4 relative;
}
.step-marker-vertical {
@apply w-8 h-8 rounded-full border-2 flex items-center justify-center flex-shrink-0;
@apply text-xs font-medium bg-white dark:bg-gray-800;
@apply border-gray-300 dark:border-gray-600 text-gray-500 dark:text-gray-400;
}
.step-item-vertical.completed .step-marker-vertical {
@apply bg-blue-500 border-blue-500 text-white;
}
.step-item-vertical.active .step-marker-vertical {
@apply border-blue-500 text-blue-500;
}
.step-content-vertical {
@apply flex-1;
}
.step-title-vertical {
@apply text-sm font-medium text-gray-900 dark:text-white;
}
.step-description-vertical {
@apply text-sm text-gray-600 dark:text-gray-300 mt-1;
}
.step-timestamp {
@apply text-xs text-gray-500 dark:text-gray-400 mt-2;
}
/* Circular Progress */
.circular-progress {
@apply relative inline-block;
width: 80px;
height: 80px;
}
.circular-progress.circular-sm {
width: 60px;
height: 60px;
}
.circular-progress.circular-lg {
width: 120px;
height: 120px;
}
.circular-svg {
@apply w-full h-full transform -rotate-90;
}
.circular-bg {
@apply fill-none stroke-gray-200 dark:stroke-gray-700;
stroke-width: 2;
}
.circular-bar {
@apply fill-none stroke-blue-500 transition-all duration-300;
stroke-width: 2;
stroke-linecap: round;
}
.circular-bar.circular-success {
@apply stroke-green-500;
}
.circular-text {
@apply absolute inset-0 flex items-center justify-center;
@apply text-sm font-medium text-gray-900 dark:text-white;
}
/* Loading States */
.loading-overlay {
@apply absolute inset-0 bg-white/80 dark:bg-gray-900/80 flex items-center justify-center;
@apply backdrop-blur-sm rounded-lg;
}
.loading-content {
@apply flex flex-col items-center justify-center text-center;
}
.btn-loading {
@apply opacity-75 cursor-not-allowed;
}