import { clsx } from 'clsx'; import { Card } from '../ui/Card'; import { LoadingSpinner } from './LoadingSpinner'; export interface SkeletonProps { className?: string; rounded?: boolean; animate?: boolean; } export interface SkeletonLayoutProps { loadingText?: string; className?: string; } /** * Base skeleton component with glassmorphism styling */ export function BaseSkeleton({ className, rounded = true, animate = true }: SkeletonProps) { return (
); } /** * Skeleton for text content */ export function TextSkeleton({ lines = 1, className, animate = true }: { lines?: number; className?: string; animate?: boolean; }) { return (
{Array.from({ length: lines }).map((_, index) => ( ))}
); } /** * Skeleton for avatars and circular elements */ export function AvatarSkeleton({ size = 'md', className }: { size?: 'sm' | 'md' | 'lg' | 'xl'; className?: string; }) { const sizeClasses = { sm: 'w-8 h-8', md: 'w-12 h-12', lg: 'w-16 h-16', xl: 'w-24 h-24' }; return ( ); } /** * Skeleton for buttons */ export function ButtonSkeleton({ size = 'md', className }: { size?: 'sm' | 'md' | 'lg'; className?: string; }) { const sizeClasses = { sm: 'h-8 w-20', md: 'h-10 w-24', lg: 'h-12 w-32' }; return ( ); } /** * Skeleton for cards */ function CardSkeleton({ loadingText, className }: SkeletonLayoutProps) { return (
{/* Loading indicator */} {loadingText && (
)} {/* Card skeletons */}
{Array.from({ length: 6 }).map((_, index) => (
{/* Header */}
{/* Content */}
{/* Footer */}
))}
); } /** * Skeleton for list items */ function ListSkeleton({ loadingText, className }: SkeletonLayoutProps) { return (
{/* Loading indicator */} {loadingText && (
)} {/* List items */} {Array.from({ length: 8 }).map((_, index) => (
))}
); } /** * Skeleton for tables */ function TableSkeleton({ loadingText, className }: SkeletonLayoutProps) { return (
{/* Loading indicator */} {loadingText && (
)} {/* Table header */}
{Array.from({ length: 5 }).map((_, index) => ( ))}
{/* Table rows */}
{Array.from({ length: 10 }).map((_, rowIndex) => (
{Array.from({ length: 5 }).map((_, colIndex) => { if (colIndex === 0) { return (
); } if (colIndex === 4) { return (
); } return ; })}
))}
); } /** * Skeleton for full page layouts */ function PageSkeleton({ loadingText, className }: SkeletonLayoutProps) { return (
{/* Header skeleton */}
{Array.from({ length: 4 }).map((_, index) => ( ))}
{/* Main content area */}
{/* Loading indicator */} {loadingText && (
)} {/* Page title and actions */}
{/* Stats cards */}
{Array.from({ length: 4 }).map((_, index) => (
))}
{/* Main content */}
{/* Primary content */}
{Array.from({ length: 6 }).map((_, index) => (
))}
{/* Sidebar */}
{Array.from({ length: 4 }).map((_, index) => (
))}
); } /** * Skeleton for form layouts */ function FormSkeleton({ loadingText, className }: SkeletonLayoutProps) { return (
{/* Loading indicator */} {loadingText && (
)}
{/* Form title */} {/* Form fields */}
{Array.from({ length: 6 }).map((_, index) => (
))}
{/* Text area */}
{/* Form actions */}
); } // Export all skeleton components export const Skeleton = { Base: BaseSkeleton, Text: TextSkeleton, Avatar: AvatarSkeleton, Button: ButtonSkeleton, Card: CardSkeleton, List: ListSkeleton, Table: TableSkeleton, Page: PageSkeleton, Form: FormSkeleton }; export default Skeleton;