+layout.svelte
2.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<script>
import '../app.css';
import { page, navigating } from '$app/stores';
import favicon from '$lib/assets/favicon.svg';
import Navbar from '$lib/components/ui/Navbar.svelte';
import NavigationDrawer from '$lib/components/layout/NavigationDrawer.svelte';
import { openDrawer } from '$lib/stores/drawer.js';
import Spinner from '$lib/components/ui/Spinner.svelte';
let { children } = $props();
// Don't show navbar on landing page
let isLanding = $derived($page.url.pathname === '/');
// Navigation loading state
let showLoader = $state(false);
let loaderTimeout = null;
let navStartTime = null;
// Show loader after 150ms delay (avoid flash for fast navigations)
$effect(() => {
if ($navigating) {
navStartTime = performance.now();
console.log(`[NAV] Navigation started → ${$navigating.to?.url?.pathname}`);
loaderTimeout = setTimeout(() => {
showLoader = true;
}, 150);
} else {
if (loaderTimeout) clearTimeout(loaderTimeout);
if (navStartTime) {
console.log(`[NAV] Navigation complete: ${(performance.now() - navStartTime).toFixed(0)}ms`);
navStartTime = null;
}
showLoader = false;
}
});
</script>
<svelte:head>
<link rel="icon" href={favicon} />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Mono:wght@400;500&family=Instrument+Sans:wght@400;500;600&display=swap" rel="stylesheet" />
</svelte:head>
<!-- Navigation Drawer (siempre presente) -->
<NavigationDrawer />
<!-- Floating controls bar (fixed position - no afecta el flujo) -->
{#if !isLanding}
<Navbar onOpenDrawer={openDrawer} />
{/if}
<!-- Navigation loading overlay -->
{#if showLoader}
<div class="nav-loader">
<div class="nav-loader-content">
<Spinner size={32} color="#C9A751" />
<span class="nav-loader-text">Cargando...</span>
</div>
</div>
{/if}
<div class="layout-wrapper">
<main class="layout-main">
{@render children()}
</main>
</div>
<style>
.layout-wrapper {
min-height: 100vh;
width: 100%;
background-color: var(--theme-body);
}
.layout-main {
width: 100%;
max-width: 100%;
overflow-x: hidden;
}
.nav-loader {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(28, 28, 26, 0.85);
backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
animation: fadeIn 0.15s ease-out;
}
.nav-loader-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}
.nav-loader-text {
font-family: 'DM Mono', monospace;
font-size: 13px;
color: #B8B5AD;
letter-spacing: 0.05em;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
</style>