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.

Progress Bars

Linear progress indicators showing completion percentage or task progress. Available in different sizes, colors, and with optional labels.

Basic Progress Bars

Overall Progress 75%
Task Completion Complete
Review Progress 45%
Critical Tasks 25%

Progress Bar Sizes

Small 60%
Medium (Default) 75%
Large 85%

Animated Progress Bars

File Upload 0%
Processing... Please wait

Spinners

Rotating loading indicators for indefinite loading states. Available in different sizes and colors to match your design needs.

Basic Spinners

Default
Primary
Success
Warning
Danger

Spinner Sizes

XS
Small
Medium
Large
XL

Spinner Variations

Dots
Pulse
Ring
Bars

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

Account Setup
Create your account
2
Personal Information
Add your details
3
Preferences
Configure settings
4
Review & Submit
Confirm and finish

Vertical Step Progress

Project Setup
Initialize project and configure settings
Completed 2 hours ago
Development
Implement core features and functionality
Completed 30 minutes ago
3
Testing
Quality assurance and bug fixing
In progress
4
Deployment
Deploy to production environment
Pending

Circular Progress

Circular progress indicators for showing completion percentage in a compact format. Ideal for dashboards and status displays.

Basic Circular Progress

75%
Small
60%
Medium
85%
Large

Interactive Circular Progress

0%

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, and aria-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 Indicators CSS Classes
/* 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;
}