import type { LucideIcon } from "lucide-react"; import { AlertTriangle, Inbox, RotateCw } from "lucide-react"; import type { ReactNode } from "react"; import { Button } from "~/components/ui/button.tsx"; import { cn } from "~/lib/utils.ts"; /** 空态:图标 + 标题 + 说明 + 可选操作。用于"尚无数据"与"功能建设中"占位 */ export function EmptyState({ icon: Icon = Inbox, title, description, action, plain = false, className, }: { icon?: LucideIcon; title: string; description?: ReactNode; action?: ReactNode; /** 放在已有卡片内时用 plain,避免玻璃叠玻璃 */ plain?: boolean; className?: string; }) { return (

{title}

{description ?

{description}

: null} {action ?
{action}
: null}
); } /** 错误态:图标 + 标题 + 错误消息 + 可选重试。放在卡片里时用 plain */ export function ErrorState({ title = "加载失败", error, onRetry, plain = false, className, }: { title?: string; error?: unknown; onRetry?: () => void; plain?: boolean; className?: string; }) { const message = error instanceof Error ? error.message : typeof error === "string" ? error : undefined; return (

{title}

{message ?

{message}

: null} {onRetry ? ( ) : null}
); } /** 加载态:若干行骨架条 */ export function LoadingState({ rows = 3, className }: { rows?: number; className?: string }) { return (
{Array.from({ length: rows }, (_, i) => (
))}
); }