import { AlertTriangle, Loader2 } from "lucide-react";
import { GlassPanel, Skeleton, Spinner } from "@/components/primitives";
import { cn } from "@/lib/utils";
/** A panel-shaped loading placeholder. */
export function SkeletonPanel({
rows = 3,
className,
}: {
rows?: number;
className?: string;
}) {
return (
{Array.from({ length: rows }).map((_, i) => (
))}
);
}
/** A 2×2 (or 4-col) grid of metric-tile placeholders. */
export function SkeletonMetricRow({ cols = 4 }: { cols?: number }) {
return (
{Array.from({ length: cols }).map((_, i) => (
))}
);
}
/** A stacked list of row placeholders (message/moderation/queue style). */
export function SkeletonRows({
rows = 6,
className,
}: {
rows?: number;
className?: string;
}) {
return (
{Array.from({ length: rows }).map((_, i) => (
))}
);
}
/** Hero block placeholder (dashboard / media "now playing"). */
export function SkeletonHero({ className }: { className?: string }) {
return (
);
}
export function EmptyState({
title = "Nothing here yet",
description,
icon,
className,
}: {
title?: string;
description?: string;
icon?: React.ReactNode;
className?: string;
}) {
return (
{icon && (
{icon}
)}
{title}
{description && (
{description}
)}
);
}
export function ErrorState({
title = "Couldn't load",
error,
onRetry,
}: {
title?: string;
error?: unknown;
onRetry?: () => void;
}) {
const msg = error instanceof Error ? error.message : String(error ?? "");
return (
{title}
{msg && (
{msg}
)}
{onRetry && (
)}
);
}
export function LoadingState({ label = "Syncing" }: { label?: string }) {
return (
{label}
);
}
export { Loader2 };