Skip to content
File

Blob: src/client/components/bootstrap-overlay.tsx

typescript44 lines
1import { useState, useEffect } from "react";
2 
3const BOOT_HINT_DELAY_MS = 5_000;
4 
5interface BootstrapOverlayProps {
6 reconnecting?: boolean;
7}
8 
9/**
10 * Prominent overlay shown over the terminal area while the WebSocket
11 * connection is being established. If connecting takes longer than 5 s
12 * (typical for a cold container boot), a secondary hint is shown.
13 */
14export function BootstrapOverlay({ reconnecting }: BootstrapOverlayProps) {
15 const [showBootHint, setShowBootHint] = useState(false);
16 
17 useEffect(() => {
18 // Only show the "container booting" hint on first connect, not reconnects
19 if (reconnecting) {
20 setShowBootHint(false);
21 return;
22 }
23 const timer = setTimeout(() => setShowBootHint(true), BOOT_HINT_DELAY_MS);
24 return () => clearTimeout(timer);
25 }, [reconnecting]);
26 
27 return (
28 <div
29 className="absolute inset-0 z-10 flex items-center justify-center bg-canvas animate-fade-in"
30 role="status"
31 aria-live="polite"
32 aria-busy="true"
33 >
34 <div className="flex flex-col items-center gap-4">
35 <div className="size-8 rounded-full border-3 border-zinc-700 border-t-zinc-100 animate-spinner" />
36 <div className="text-zinc-100 text-sm">
37 {reconnecting ? "Reconnecting to session\u2026" : "Connecting to container\u2026"}
38 </div>
39 {showBootHint && <div className="text-zinc-500 text-xs">Container is starting up — this can take a moment</div>}
40 </div>
41 </div>
42 );
43}