Gemma4-WebGPU / src /components /LoadingScreen.tsx
BryanBradfo's picture
Gemma 4 multimodal WebGPU detection Space
576d07a
import { Loader2 } from "lucide-react";
import type { LoadingStatus } from "../hooks/LLMContext";
interface LoadingScreenProps {
status: LoadingStatus;
}
export function LoadingScreen({ status }: LoadingScreenProps) {
const progress =
status.state === "ready"
? 100
: status.state === "loading" && typeof status.progress === "number"
? status.progress
: 0;
const message =
status.state === "loading"
? status.message ?? "Loading model..."
: status.state === "error"
? "Failed to load model"
: "Initializing...";
return (
<div className="absolute inset-0 flex items-center justify-center bg-[#0a0a0a] text-white animate-fade-in">
<div className="w-full max-w-md px-6 flex flex-col items-center">
<div className="mb-10 flex items-center gap-3">
<div className="w-9 h-9 rounded-lg bg-[#1a73e8] flex items-center justify-center">
<svg viewBox="0 0 100 100" className="w-5 h-5">
<polygon
points="50,10 85,35 72,85 28,85 15,35"
fill="rgba(255,255,255,0.95)"
/>
<polygon
points="50,10 62,35 50,85 38,35"
fill="rgba(255,255,255,0.55)"
/>
</svg>
</div>
<span className="text-lg font-medium tracking-tight">Gemma 4</span>
</div>
{status.state !== "error" && (
<Loader2 className="h-8 w-8 animate-spin text-[#1a73e8] mb-4" />
)}
<p
className={`text-sm tracking-wide ${
status.state === "error"
? "text-red-400 font-medium"
: "text-white/70"
}`}
>
{message}
</p>
<div className="mt-6 h-1 w-full rounded-full bg-white/10 overflow-hidden">
<div
className="h-full rounded-full bg-[#1a73e8] transition-[width] duration-300 ease-out"
style={{ width: `${progress}%` }}
/>
</div>
<p className="mt-4 text-xs text-white/40">
Cached after first load · Runs 100% offline
</p>
{status.state === "error" && (
<p className="mt-3 text-sm text-red-400 text-center">{status.error}</p>
)}
</div>
</div>
);
}