Files
xingrin/frontend/components/loading-spinner.tsx

93 lines
2.0 KiB
TypeScript
Raw Normal View History

2025-12-12 18:04:57 +08:00
"use client"
import React from "react"
import { cn } from "@/lib/utils"
import { Spinner } from "@/components/ui/spinner"
interface LoadingSpinnerProps {
size?: "sm" | "md" | "lg"
className?: string
}
/**
*
*
*
* - sm(16px), md(24px), lg(32px)
* -
* - 使 Tailwind CSS
*/
export function LoadingSpinner({ size = "sm", className }: LoadingSpinnerProps) {
const sizeMap = {
sm: "size-4",
md: "size-6",
lg: "size-8"
}
return <Spinner className={cn(sizeMap[size], className)} />
}
interface LoadingStateProps {
message?: string
size?: "sm" | "md" | "lg"
className?: string
}
/**
*
*
*
*/
export function LoadingState({
message = "加载中...",
size = "md",
className
}: LoadingStateProps) {
const sizeMap = {
sm: "size-4",
md: "size-6",
lg: "size-8"
}
return (
<div className={cn("flex items-center justify-center min-h-[200px] h-screen w-full", className)}>
<div className="flex flex-col items-center space-y-4">
<Spinner className={sizeMap[size]} />
<p className="text-sm text-muted-foreground">{message}</p>
</div>
</div>
)
}
interface LoadingOverlayProps {
isLoading: boolean
message?: string
children: React.ReactNode
}
/**
*
*
*
*/
export function LoadingOverlay({
isLoading,
message = "加载中...",
children
}: LoadingOverlayProps) {
return (
<div className="relative">
{children}
{isLoading && (
<div className="absolute inset-0 bg-background/80 backdrop-blur-sm flex items-center justify-center z-50">
<div className="flex flex-col items-center space-y-2">
<LoadingSpinner size="lg" />
<p className="text-sm text-muted-foreground">{message}</p>
</div>
</div>
)}
</div>
)
}