← back to Watches

src/components/SkeletonLoader.jsx

76 lines

import React from 'react';
import { motion } from 'framer-motion';

/**
 * Skeleton loader for watch cards
 * Provides better perceived performance during data loading
 */
export function WatchCardSkeleton() {
  return (
    <div className="bg-white dark:bg-gray-800 rounded-lg shadow-md overflow-hidden">
      <div className="relative h-64 bg-gray-200 dark:bg-gray-700 animate-pulse" />
      <div className="gradient-omega p-4 space-y-2">
        <div className="h-6 bg-white/20 rounded animate-pulse" />
        <div className="h-4 bg-white/20 rounded w-2/3 animate-pulse" />
      </div>
      <div className="p-4 space-y-4">
        <div className="bg-gray-100 dark:bg-gray-700 p-3 rounded-lg space-y-2">
          <div className="grid grid-cols-2 gap-2">
            {[1, 2, 3, 4].map(i => (
              <div key={i} className="h-4 bg-gray-200 dark:bg-gray-600 rounded animate-pulse" />
            ))}
          </div>
        </div>
        <div className="space-y-2">
          <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded animate-pulse" />
          <div className="h-6 bg-gray-200 dark:bg-gray-700 rounded animate-pulse" />
        </div>
        <div className="grid grid-cols-2 gap-4">
          <div className="h-12 bg-gray-200 dark:bg-gray-700 rounded animate-pulse" />
          <div className="h-12 bg-gray-200 dark:bg-gray-700 rounded animate-pulse" />
        </div>
        <div className="h-10 bg-gray-200 dark:bg-gray-700 rounded animate-pulse" />
      </div>
    </div>
  );
}

/**
 * Skeleton loader for dashboard stats
 */
export function StatCardSkeleton() {
  return (
    <div className="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
      <div className="flex items-center justify-between">
        <div className="space-y-2 flex-1">
          <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-24 animate-pulse" />
          <div className="h-8 bg-gray-200 dark:bg-gray-700 rounded w-16 animate-pulse" />
        </div>
        <div className="w-16 h-16 bg-gray-200 dark:bg-gray-700 rounded-full animate-pulse" />
      </div>
    </div>
  );
}

/**
 * Grid of skeleton loaders
 */
export function WatchGridSkeleton({ count = 6 }) {
  return (
    <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
      {Array.from({ length: count }).map((_, i) => (
        <motion.div
          key={i}
          initial={{ opacity: 0, y: 20 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ delay: i * 0.05 }}
        >
          <WatchCardSkeleton />
        </motion.div>
      ))}
    </div>
  );
}

export default WatchCardSkeleton;