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;