forked from ORGANISATION-KA-INTERNATIONALE/FEDIVERSE-OKI
176 lines
3.4 KiB
Svelte
176 lines
3.4 KiB
Svelte
|
|
<script lang="ts">
|
||
|
|
import '$lib/styles/oki-tokens.css';
|
||
|
|
import '$lib/styles/base.css';
|
||
|
|
import { onNavigate } from '$app/navigation';
|
||
|
|
import Footer from '$lib/components/Footer.svelte';
|
||
|
|
import Nav from '$lib/components/Nav.svelte';
|
||
|
|
import Sidebar from '$lib/components/Sidebar.svelte';
|
||
|
|
import ScrollProgressBar from '$lib/components/motion/ScrollProgressBar.svelte';
|
||
|
|
import { prefersReducedMotion } from '$lib/motion/tokens';
|
||
|
|
import type { LayoutProps } from './$types';
|
||
|
|
|
||
|
|
let { data, children }: LayoutProps = $props();
|
||
|
|
|
||
|
|
let menuOpen = $state(false);
|
||
|
|
|
||
|
|
onNavigate((navigation) => {
|
||
|
|
if (prefersReducedMotion()) return;
|
||
|
|
if (!('startViewTransition' in document)) return;
|
||
|
|
return new Promise((resolve) => {
|
||
|
|
document.startViewTransition(async () => {
|
||
|
|
resolve();
|
||
|
|
await navigation.complete;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<svelte:head>
|
||
|
|
<meta name="generator" content="SvelteKit" />
|
||
|
|
</svelte:head>
|
||
|
|
|
||
|
|
<a href="#main-content" class="skip-link">{data.t.nav.skipToContent}</a>
|
||
|
|
<ScrollProgressBar label={data.t.a11y.progressLabel} />
|
||
|
|
|
||
|
|
<Nav
|
||
|
|
locale={data.locale}
|
||
|
|
t={data.t}
|
||
|
|
{menuOpen}
|
||
|
|
onToggleMenu={() => (menuOpen = !menuOpen)}
|
||
|
|
/>
|
||
|
|
|
||
|
|
<div class="shell">
|
||
|
|
<aside class="sidebar">
|
||
|
|
<Sidebar locale={data.locale} t={data.t} />
|
||
|
|
</aside>
|
||
|
|
|
||
|
|
{#if menuOpen}
|
||
|
|
<div class="drawer-backdrop" onclick={() => (menuOpen = false)} aria-hidden="true"></div>
|
||
|
|
{/if}
|
||
|
|
<aside
|
||
|
|
id="mobile-menu"
|
||
|
|
class="drawer"
|
||
|
|
class:open={menuOpen}
|
||
|
|
aria-label={data.t.nav.mainLabel}
|
||
|
|
inert={!menuOpen}
|
||
|
|
>
|
||
|
|
<Sidebar locale={data.locale} t={data.t} onNavigate={() => (menuOpen = false)} />
|
||
|
|
</aside>
|
||
|
|
|
||
|
|
<div class="content">
|
||
|
|
<main id="main-content" class="main-content">
|
||
|
|
{@render children()}
|
||
|
|
</main>
|
||
|
|
<Footer locale={data.locale} t={data.t} />
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<style>
|
||
|
|
.shell {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: var(--sidebar-w) 1fr;
|
||
|
|
flex: 1;
|
||
|
|
min-height: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar {
|
||
|
|
border-right: 1px solid var(--line);
|
||
|
|
background: var(--surface);
|
||
|
|
overflow-y: auto;
|
||
|
|
position: sticky;
|
||
|
|
top: calc(var(--header-h) + 6px);
|
||
|
|
height: calc(100dvh - var(--header-h) - 6px);
|
||
|
|
}
|
||
|
|
|
||
|
|
.content {
|
||
|
|
min-width: 0;
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
}
|
||
|
|
|
||
|
|
.main-content {
|
||
|
|
flex: 1;
|
||
|
|
padding: var(--space-3);
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
gap: var(--space-4);
|
||
|
|
}
|
||
|
|
|
||
|
|
.drawer {
|
||
|
|
display: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (max-width: 900px) {
|
||
|
|
.shell {
|
||
|
|
grid-template-columns: 1fr;
|
||
|
|
}
|
||
|
|
|
||
|
|
.sidebar {
|
||
|
|
display: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
.drawer {
|
||
|
|
display: block;
|
||
|
|
position: fixed;
|
||
|
|
top: 0;
|
||
|
|
left: 0;
|
||
|
|
bottom: 0;
|
||
|
|
width: min(300px, 85vw);
|
||
|
|
z-index: 280;
|
||
|
|
background: var(--surface);
|
||
|
|
border-right: 1px solid var(--line);
|
||
|
|
overflow-y: auto;
|
||
|
|
transform: translateX(-100%);
|
||
|
|
transition: transform var(--dur-mesure) var(--ease-ka);
|
||
|
|
}
|
||
|
|
|
||
|
|
.drawer.open {
|
||
|
|
transform: translateX(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
.drawer-backdrop {
|
||
|
|
position: fixed;
|
||
|
|
inset: 0;
|
||
|
|
z-index: 270;
|
||
|
|
background: rgba(13, 13, 13, 0.6);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (prefers-reduced-motion: reduce) {
|
||
|
|
.drawer {
|
||
|
|
transition: none;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@view-transition {
|
||
|
|
navigation: auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
@keyframes vt-fade-in {
|
||
|
|
from {
|
||
|
|
opacity: 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
@keyframes vt-fade-out {
|
||
|
|
to {
|
||
|
|
opacity: 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
::view-transition-old(root) {
|
||
|
|
animation: vt-fade-out var(--dur-mesure) var(--ease-ka) both;
|
||
|
|
}
|
||
|
|
|
||
|
|
::view-transition-new(root) {
|
||
|
|
animation: vt-fade-in var(--dur-mesure) var(--ease-ka) both;
|
||
|
|
}
|
||
|
|
|
||
|
|
@media (prefers-reduced-motion: reduce) {
|
||
|
|
::view-transition-old(root),
|
||
|
|
::view-transition-new(root) {
|
||
|
|
animation: none;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</style>
|