Full-page branded loading screen with logo and progress
Tags: component feedback loading page
A full-viewport loading screen for initial app loads, route transitions, or long-running operations. Displays the Classic Homes branded logo with optional progress bar and message.
Import
<script>
import { LoadingPage } from '@classic-homes/theme-svelte';
</script>import { LoadingPage } from '@classic-homes/theme-react';Basic Usage
{#if appLoading}
<LoadingPage loading message="Loading your experience..." />
{/if}Props
| Prop | Type | Default | Description |
|---|---|---|---|
loading |
boolean |
true |
Whether loading is active |
message |
string |
- | Loading message (e.g. "Loading...") |
progress |
number |
- | Determinate progress value (0–100) |
showLogo |
boolean |
true |
Show branded LoadingLogo |
logoVariant |
'light' | 'dark' |
'dark' |
Logo color variant |
delay |
number |
200 |
Delay in ms before showing |
class |
string |
- | Additional CSS classes |
Layout
The component renders a fixed full-viewport overlay with centered content:
- Logo — Animated Classic Homes logo (or Spinner if
showLogo=false) - Progress bar — Shown only when
progressis provided - Message — Subtle pulsing text below the indicator
- Status region — Screen reader announcement of state
Delay
The default 200ms delay prevents a flash of loading screen for fast page transitions. Set delay={0} to show immediately.
<!-- Immediate display -->
<LoadingPage loading delay={0} />
<!-- Custom delay -->
<LoadingPage loading delay={500} />Examples
App Initialization
<script>
import { LoadingPage } from '@classic-homes/theme-svelte';
let appReady = $state(false);
onMount(async () => {
await initializeApp();
appReady = true;
});
</script>
{#if !appReady}
<LoadingPage loading message="Initializing..." />
{/if}
{#if appReady}
<App />
{/if}With Progress
Show determinate progress for operations with known duration:
<script>
let progress = $state(0);
let message = $state('Downloading resources...');
async function loadApp() {
for (let i = 0; i <= 100; i += 10) {
progress = i;
if (i >= 50) message = 'Processing data...';
if (i >= 80) message = 'Almost done...';
await new Promise((r) => setTimeout(r, 200));
}
}
</script>
<LoadingPage loading {progress} {message} />Without Logo
Use a plain spinner instead of the branded logo:
<LoadingPage loading showLogo={false} message="Loading..." />Light Variant (Dark Background)
If your app has a dark initial background:
<LoadingPage loading logoVariant="light" class="bg-gray-900" />Route Transition
<!-- SvelteKit layout -->
<script>
import { navigating } from '$app/stores';
import { LoadingPage } from '@classic-homes/theme-svelte';
</script>
{#if $navigating}
<LoadingPage loading message="Loading page..." delay={300} />
{/if}
<slot />React Suspense Fallback
import { Suspense } from 'react';
import { LoadingPage } from '@classic-homes/theme-react';
function App() {
return (
<Suspense fallback={<LoadingPage loading message="Loading..." />}>
<Routes />
</Suspense>
);
}Accessibility
- Uses
role="status"andaria-live="polite"for screen reader announcements - Provides an sr-only status region combining message and progress percentage
- The animated logo has
aria-hidden="true"on the SVG and a separate sr-only "Loading" text - Animation respects
prefers-reduced-motion
Related Components
- LoadingOverlay - Lower-level overlay for any scope
- LoadingSection - Section-level loading wrapper
- LoadingLogo - Standalone animated logo
- ProgressBar - Standalone progress bar
- Spinner - Simple loading indicator