summaryrefslogtreecommitdiffstatshomepage
path: root/frontend/src/routes/+layout.svelte
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/routes/+layout.svelte')
-rw-r--r--frontend/src/routes/+layout.svelte95
1 files changed, 95 insertions, 0 deletions
diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte
new file mode 100644
index 0000000..0eefed1
--- /dev/null
+++ b/frontend/src/routes/+layout.svelte
@@ -0,0 +1,95 @@
+<script lang="ts">
+ import { addShortcut, handleShortcuts } from '$lib/Shortcuts';
+ import { fadeDefault } from '$lib/Transitions';
+ import AddArtist from '$lib/dialogs/AddArtist.svelte';
+ import AddCharacter from '$lib/dialogs/AddCharacter.svelte';
+ import AddCircle from '$lib/dialogs/AddCircle.svelte';
+ import AddNamespace from '$lib/dialogs/AddNamespace.svelte';
+ import AddTag from '$lib/dialogs/AddTag.svelte';
+ import AddWorld from '$lib/dialogs/AddWorld.svelte';
+ import Link from '$lib/navigation/Link.svelte';
+ import Navigation from '$lib/navigation/Navigation.svelte';
+ import { cacheExchange, fetchExchange, initContextClient } from '@urql/svelte';
+ import { SvelteToast } from '@zerodevx/svelte-toast';
+ import { Modals, closeModal, openModal } from 'svelte-modals';
+ import { fade } from 'svelte/transition';
+ import '../app.css';
+
+ initContextClient({
+ url: import.meta.env.VITE_GQL_ENDPOINT ?? '/graphql',
+ exchanges: [cacheExchange, fetchExchange]
+ });
+
+ addShortcut('na', () => openModal(AddArtist));
+ addShortcut('nh', () => openModal(AddCharacter));
+ addShortcut('ni', () => openModal(AddCircle));
+ addShortcut('nn', () => openModal(AddNamespace));
+ addShortcut('nt', () => openModal(AddTag));
+ addShortcut('nw', () => openModal(AddWorld));
+
+ function keydown(event: KeyboardEvent) {
+ handleShortcuts(event);
+ }
+</script>
+
+<svelte:document on:keydown={keydown} />
+
+<Navigation>
+ <Link matchExact href="/" title="Home" accel="go">
+ <span class="icon-base icon-[material-symbols--home]" />
+ </Link>
+ <Link href="/comics/" title="Comics" accel="gc">
+ <span class="icon-base icon-[material-symbols--menu-book]" />
+ </Link>
+ <Link href="/namespaces/" title="Namespaces" accel="gn">
+ <span class="icon-base icon-[material-symbols--inbox]" />
+ </Link>
+ <Link href="/tags/" title="Tags" accel="gt">
+ <span class="icon-base icon-[material-symbols--label]" />
+ </Link>
+ <Link href="/artists/" title="Artists" accel="ga">
+ <span class="icon-base icon-[material-symbols--person]" />
+ </Link>
+ <Link href="/circles/" title="Circles" accel="gi">
+ <span class="icon-base icon-[material-symbols--group]" />
+ </Link>
+ <Link href="/characters/" title="Characters" accel="gh">
+ <span class="icon-base icon-[material-symbols--face]" />
+ </Link>
+ <Link href="/worlds/" title="Worlds" accel="gw">
+ <span class="icon-base icon-[material-symbols--public]" />
+ </Link>
+ <Link href="/archives/" title="Archives" accel="gz">
+ <span class="icon-base icon-[material-symbols--folder-zip]" />
+ </Link>
+ <div class="mb-auto" />
+ <Link href="/help/" title="Help" accel="?" target="_blank">
+ <span class="icon-base icon-[material-symbols--help]" />
+ </Link>
+</Navigation>
+
+<div class="min-w-[360px] overflow-auto p-4">
+ <slot />
+</div>
+
+<Modals>
+ <!-- svelte-ignore a11y-no-static-element-interactions -->
+ <!-- svelte-ignore a11y-click-events-have-key-events -->
+ <div
+ slot="backdrop"
+ on:click={closeModal}
+ transition:fade={fadeDefault}
+ class="fixed bottom-0 left-0 right-0 top-0 z-20 bg-stone-800/80"
+ />
+</Modals>
+
+<SvelteToast options={{ reversed: true, intro: { y: 192 } }} />
+
+<style>
+ :root {
+ --toastBarHeight: 0;
+ --toastContainerTop: auto;
+ --toastContainerLeft: 4rem;
+ --toastContainerBottom: 1rem;
+ }
+</style>