Assist_Design/apps/portal/src/components/atoms/loading-skeleton.tsx
barsa b99799c2fe Refactor UI components and enhance styling consistency across the portal
- Updated various components to use consistent color tokens, improving visual coherence.
- Refactored layout components to utilize the new PublicShell for better structure.
- Enhanced error and status messaging styles for improved user feedback.
- Standardized button usage across forms and modals for a unified interaction experience.
- Introduced new UI design tokens and guidelines in documentation to support future development.
2025-12-16 13:54:31 +09:00

97 lines
3.1 KiB
TypeScript

import { cn } from "@/lib/utils";
interface SkeletonProps {
className?: string;
animate?: boolean;
}
export function Skeleton({ className, animate = true }: SkeletonProps) {
return (
<div
className={cn(
"bg-[var(--cp-skeleton-base)] rounded-md",
animate && "animate-pulse",
className
)}
/>
);
}
export function LoadingCard({ className }: { className?: string }) {
return (
<div
className={cn(
"bg-card text-card-foreground border border-border rounded-[var(--cp-card-radius)] p-[var(--cp-card-padding)] shadow-[var(--cp-card-shadow)]",
className
)}
>
<div className="space-y-4">
<div className="flex items-center space-x-3">
<Skeleton className="h-8 w-8 rounded-full" />
<div className="space-y-2 flex-1">
<Skeleton className="h-4 w-1/3" />
<Skeleton className="h-3 w-1/2" />
</div>
</div>
<div className="space-y-2">
<Skeleton className="h-3 w-full" />
<Skeleton className="h-3 w-4/5" />
<Skeleton className="h-3 w-3/5" />
</div>
</div>
</div>
);
}
export function LoadingTable({ rows = 5, columns = 4 }: { rows?: number; columns?: number }) {
return (
<div className="bg-card text-card-foreground border border-border rounded-[var(--cp-card-radius)] overflow-hidden">
{/* Header */}
<div className="border-b border-border p-4">
<div className="grid gap-4" style={{ gridTemplateColumns: `repeat(${columns}, 1fr)` }}>
{Array.from({ length: columns }).map((_, i) => (
<Skeleton key={i} className="h-4 w-20" />
))}
</div>
</div>
{/* Rows */}
<div className="divide-y divide-border">
{Array.from({ length: rows }).map((_, rowIndex) => (
<div key={rowIndex} className="p-4">
<div className="grid gap-4" style={{ gridTemplateColumns: `repeat(${columns}, 1fr)` }}>
{Array.from({ length: columns }).map((_, colIndex) => (
<Skeleton key={colIndex} className="h-4 w-full" />
))}
</div>
</div>
))}
</div>
</div>
);
}
export function LoadingStats({ count = 4 }: { count?: number }) {
return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{Array.from({ length: count }).map((_, i) => (
<div
key={i}
className="bg-card text-card-foreground border border-border rounded-[var(--cp-card-radius)] p-[var(--cp-card-padding)] shadow-[var(--cp-card-shadow)]"
>
<div className="flex items-center">
<Skeleton className="h-8 w-8 rounded-full" />
<div className="ml-4 space-y-2 flex-1">
<Skeleton className="h-4 w-16" />
<Skeleton className="h-6 w-12" />
</div>
</div>
</div>
))}
</div>
);
}
// Note: PageLoadingState is now handled by PageLayout component with proper skeleton loading
// FullPageLoadingState removed - use skeleton loading instead