ensure the fullscreen countdown is always on top and not restricted to the parent bounds

This commit is contained in:
Oliver Bryan
2026-01-01 02:27:11 +00:00
parent 0860217d99
commit a9bbb30285

View File

@@ -1,5 +1,6 @@
import { CheckIcon, ServerIcon, Undo2 } from "lucide-react"; import { CheckIcon, ServerIcon, Undo2 } from "lucide-react";
import { type ReactNode, useState } from "react"; import { type ReactNode, useState } from "react";
import { createPortal } from "react-dom";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
@@ -108,76 +109,79 @@ export function ServerConfigurationDialog({ trigger }: { trigger?: ReactNode })
}; };
return ( return (
<Dialog open={open} onOpenChange={handleOpenChange}> <>
<DialogTrigger asChild> <Dialog open={open} onOpenChange={handleOpenChange}>
{trigger || ( <DialogTrigger asChild>
<Button {trigger || (
variant="ghost" <Button
size="icon" variant="ghost"
className="absolute top-2 right-2" size="icon"
title="Server Configuration" className="absolute top-2 right-2"
> title="Server Configuration"
<ServerIcon className="size-4" /> >
</Button> <ServerIcon className="size-4" />
)} </Button>
</DialogTrigger> )}
</DialogTrigger>
<DialogContent> <DialogContent>
<DialogHeader> <DialogHeader>
<DialogTitle>Server Configuration</DialogTitle> <DialogTitle>Server Configuration</DialogTitle>
</DialogHeader> </DialogHeader>
<div className="grid gap-4"> <div className="grid gap-4">
<div className="grid gap-2"> <div className="grid gap-2">
<Label htmlFor="server-url">Server URL</Label> <Label htmlFor="server-url">Server URL</Label>
<div className="flex gap-2"> <div className="flex gap-2">
<Input <Input
id="server-url" id="server-url"
value={serverURL} value={serverURL}
onChange={(e) => handleServerURLChange(e.target.value)} onChange={(e) => handleServerURLChange(e.target.value)}
onKeyDown={(e) => { onKeyDown={(e) => {
if (e.key === "Enter" && canSave && !isCheckingHealth) { if (e.key === "Enter" && canSave && !isCheckingHealth) {
e.preventDefault(); e.preventDefault();
void handleSave(); void handleSave();
} }
}} }}
placeholder="https://example.com" placeholder="https://example.com"
className={!isValid ? "border-destructive" : ""} className={!isValid ? "border-destructive" : ""}
/> />
<Button <Button
type="button" type="button"
size="icon" size="icon"
variant={canSave ? "default" : "outline"} variant={canSave ? "default" : "outline"}
disabled={!canSave || isCheckingHealth} disabled={!canSave || isCheckingHealth}
onClick={handleSave} onClick={handleSave}
> >
<CheckIcon className="size-4" /> <CheckIcon className="size-4" />
</Button> </Button>
<Button <Button
type="button" type="button"
size="icon" size="icon"
variant="secondary" variant="secondary"
disabled={!isNotDefault || isCheckingHealth} disabled={!isNotDefault || isCheckingHealth}
onClick={handleResetToDefault} onClick={handleResetToDefault}
title="Reset to default" title="Reset to default"
> >
<Undo2 className="size-4" /> <Undo2 className="size-4" />
</Button> </Button>
</div>
{!isValid && (
<Label className="text-destructive text-sm">Please enter a valid URL</Label>
)}
{healthError && <Label className="text-destructive text-sm">{healthError}</Label>}
</div> </div>
{!isValid && (
<Label className="text-destructive text-sm">Please enter a valid URL</Label>
)}
{healthError && <Label className="text-destructive text-sm">{healthError}</Label>}
</div> </div>
</div> </DialogContent>
</DialogContent> </Dialog>
{countdown !== null &&
{countdown !== null && ( createPortal(
<div className="fixed inset-0 z-[100] bg-black/50 flex flex-col items-center justify-center pointer-events-auto"> <div className="fixed inset-0 z-[100] bg-black/50 flex flex-col items-center justify-center pointer-events-auto">
<div className="text-2xl font-bold pointer-events-none noselect">Redirecting</div> <div className="text-2xl font-bold pointer-events-none noselect">Redirecting</div>
<div className="text-8xl font-bold pointer-events-none noselect">{countdown}</div> <div className="text-8xl font-bold pointer-events-none noselect">{countdown}</div>
</div> </div>,
)} document.body,
</Dialog> )}
</>
); );
} }