floter.design/src/routes/+layout.svelte
2026-02-14 17:35:00 +01:00

87 lines
No EOL
2.8 KiB
Svelte

<script lang="ts">
import '$lib/styles/global.css';
import Header from '$lib/components/Header.svelte';
import Loader from '$lib/components/Loader.svelte';
import { page } from '$app/state';
import { beforeNavigate } from '$app/navigation';
import { browser } from '$app/environment';
import type { Snippet } from 'svelte';
import { onMount } from 'svelte';
interface LayoutData {
pathname: string;
}
onMount(() => {
// console.log('layout mounted');
setTheme();
});
let { children }: { children: Snippet } = $props();
let showLoader = $state(false);
let timer: ReturnType<typeof setTimeout> | null = null;
let navToken = 0;
function clearTimer() {
if (timer) {
clearTimeout(timer);
timer = null;
}
}
if (browser) {
beforeNavigate((nav) => {
// token to avoid races between overlapping navigations
const token = ++navToken;
clearTimer();
showLoader = false;
// only show if navigation takes >150ms
timer = setTimeout(() => {
if (token === navToken) showLoader = true;
}, 150);
// hide loader when THIS navigation completes (even if afterNavigate timing is odd)
nav.complete.finally(() => {
if (token !== navToken) return;
clearTimer();
showLoader = false;
setTheme();
});
});
}
function setTheme() {
if (page.data.theme && page.data.theme.bg && page.data.theme.text && page.data.theme.highlight) {
document.documentElement.style.setProperty('--color-bg', page.data.theme.bg);
document.documentElement.style.setProperty('--color-text', page.data.theme.text);
document.documentElement.style.setProperty('--color-highlight', page.data.theme.highlight);
} else {
// Remove inline styles to let CSS :root defaults take effect
document.documentElement.style.removeProperty('--color-bg');
document.documentElement.style.removeProperty('--color-text');
document.documentElement.style.removeProperty('--color-highlight');
}
}
</script>
<svelte:head>
<meta property="og:type" content="website" />
<meta property="og:url" content={`https://floter.design${page.url.pathname}`} />
<meta property="og:image" content="https://floter.design/ogimage.png">
<meta name="twitter:card" content="summary_large_image">
<meta name="description" content={page.data.description ? page.data.description : 'Simon Flöter is a designer and creative developer'} />
<title>{page.data.title ? page.data.title : 'Simon Flöter, Designer and Creative Developer'}</title>
<script defer data-domain="floter.design" src="https://analytics.floter.design/js/script.js"></script>
</svelte:head>
<Header />
<div class="content">
{#if showLoader}
<Loader />
{/if}
{@render children()}
</div>