Load preloader
A full-screen cover with a big 0 to 100 count that tracks real loading, then fades away.
Behaviour
- The count eases toward the real load but never runs ahead of the minimum-time ramp, so it always looks continuous.
- At 100 it holds for 250ms, then fades out over 1s; page scroll unlocks as the fade starts (padded for the scrollbar while locked).
- The number is written straight to the text node, so React does not re-render every frame.
- On a repeat visit an inline script hides it before the first paint; with no JavaScript it uncovers the page by itself.
- Reduced motion: the number jumps with the load instead of counting, with no minimum time, then a 0.3s fade.
Props
| Prop | Type | Description |
|---|---|---|
| ready | Promise<unknown> | booleandefault fonts + window load | What it waits for: a promise (settled either way counts) or a flag that turns true. |
| minDuration | numberdefault 1.2 | Seconds the count takes at the least, so a fast load still reads as intentional. |
| maxWait | numberdefault 7 | Seconds it waits at most before it counts to 100 anyway. |
| storageKey | string | falsedefault "load-preloader-seen" | sessionStorage key that makes it play once per tab; false plays it every load. |
| onDone | () => void | Called when it reaches 100 and starts to fade, releasing the page (right away when already seen). |
| contained | booleandefault false | Fill the nearest relative parent and leave page scroll alone: for a card or preview. |
Installation
npx shadcn@latest add https://purrfectui.com/r/load-preloader.jsonHow to use
import { LoadPreloader } from "@/components/ui/load-preloader";
// in your root layout, once
<LoadPreloader />
<LoadPreloader ready={heroImage.decode()} minDuration={1.5} onDone={() => console.log("in")} />Source code
Loading…
License
MIT. Copy it into your project and change it as you like.