freezmo/components/LinkLoadingScreen.tsx
Martin Dvorak 9b9e978ef2 Link loading overlay escapes the glass card (portal to body)
The full-screen loading screen shown the instant a Link starts navigating
was rendered inside the Smart Review card. That card has backdrop-filter,
which makes it a containing block for position: fixed — so the overlay was
confined to a 44px strip of the card and the loading block spilled below the
fold instead of covering the viewport. It is now portalled to <body> with a
soft page scrim behind it; the review suite measures that it covers the
viewport (390x844).

SW -> freezmo-v48.
2026-10-12 19:04:38 +00:00

30 lines
1.1 KiB
TypeScript

"use client";
import { useLinkStatus } from "next/link";
import { createPortal } from "react-dom";
import { RouteLoading } from "@/components/RouteLoading";
/**
* A full-screen loading screen that appears the instant the surrounding
* `<Link>` starts navigating — before any response arrives — so a slow route
* never looks like a dead tap. Renders nothing while idle and disappears with
* the page that owns it.
*
* Portalled to <body>: the link sits inside a glass card, and `backdrop-filter`
* makes such an ancestor a containing block for `position: fixed` — rendered
* in place, the overlay was confined to a 44px strip of the card instead of the
* viewport.
*/
export function LinkLoadingScreen({ messageKey }: { messageKey: string }) {
const { pending } = useLinkStatus();
if (!pending || typeof document === "undefined") return null;
return createPortal(
<div className="pointer-events-none fixed inset-0 z-50 bg-[color-mix(in_oklab,var(--page)_88%,transparent)]">
<RouteLoading messageKey={messageKey} />
</div>,
document.body,
);
}