← 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;