138 lines
4.8 KiB
Svelte
138 lines
4.8 KiB
Svelte
<script lang="ts">
|
|
import Logo from "./lib/components/icons/logo/Logo.svelte";
|
|
import sunIcon from "./assets/icons/sun.svg";
|
|
import moonIcon from "./assets/icons/moon.svg";
|
|
import { slide } from "svelte/transition";
|
|
import Toggle from "./lib/components/Toggle.svelte";
|
|
import { darkTheme } from "./lib/stores/theme";
|
|
import { Routes } from "./lib/global/routes";
|
|
import { isCurrentPath } from "./lib/components/Router.svelte";
|
|
|
|
let sidebarOpen = false;
|
|
|
|
function toggleMenuOpen() {
|
|
sidebarOpen = !sidebarOpen;
|
|
}
|
|
</script>
|
|
|
|
<header
|
|
class="sticky top-0 z-20 flex h-16 justify-center border-b-2 border-contrast-100 bg-primary-100 shadow-lg"
|
|
>
|
|
<div
|
|
class="flex w-full max-w-7xl flex-row items-center justify-between p-4"
|
|
>
|
|
<a class="h-full grow" href="/">
|
|
<Logo />
|
|
</a>
|
|
<ul
|
|
class="hidden flex-row justify-end gap-10 font-medium uppercase md:text-lg lg:flex"
|
|
>
|
|
{#each Routes.topbarRoutes as route}
|
|
<li>
|
|
<a
|
|
class:border-b-2={isCurrentPath(route.url)}
|
|
class="border-b-0 border-accent transition-colors hover:text-accent"
|
|
href={route.url}
|
|
target={route.target}
|
|
>
|
|
{route.text}
|
|
</a>
|
|
</li>
|
|
{/each}
|
|
</ul>
|
|
<div
|
|
class="ml-12 flex aspect-square h-full items-center justify-center p-1"
|
|
>
|
|
<button
|
|
class="hamburger-icon relative inline-block h-full w-full cursor-pointer text-contrast-100"
|
|
aria-label="open sidebar"
|
|
class:open={sidebarOpen}
|
|
on:click={toggleMenuOpen}
|
|
>
|
|
<div
|
|
class="line absolute top-0 h-0.5 w-full origin-top-left rounded-full bg-contrast-900 transition-all"
|
|
></div>
|
|
<div
|
|
class="line middle absolute top-1/2 h-0.5 w-full -translate-y-1/2 rounded-full bg-contrast-900 transition-all delay-100"
|
|
></div>
|
|
<div
|
|
class="line absolute bottom-0 h-0.5 w-full origin-bottom-left rounded-full bg-contrast-900 transition-all"
|
|
></div>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
{#if sidebarOpen}
|
|
<aside>
|
|
<nav
|
|
transition:slide={{ axis: "x" }}
|
|
class="fixed bottom-14 right-0 top-16 z-10 flex max-w-full flex-col overflow-auto border-l-2 border-contrast-100 bg-primary-100 px-4 py-8 shadow-lg sm:bottom-0"
|
|
>
|
|
<ul
|
|
class="flex grow flex-col gap-2 pr-20 text-lg font-medium lg:text-xl"
|
|
>
|
|
{#each Routes.sidebarRoutes as route}
|
|
<li>
|
|
<a
|
|
class:border-b-2={isCurrentPath(route.url)}
|
|
class="border-b-0 border-accent transition-colors hover:text-accent"
|
|
href={route.url}
|
|
target={route.target}
|
|
>
|
|
{route.text}
|
|
</a>
|
|
</li>
|
|
{/each}
|
|
</ul>
|
|
<div class="flex w-fit flex-col items-center gap-3">
|
|
<Toggle
|
|
invertColor={true}
|
|
checked={$darkTheme}
|
|
leftIcon={sunIcon}
|
|
rightIcon={moonIcon}
|
|
on:change={() => {
|
|
$darkTheme = $darkTheme = !$darkTheme;
|
|
}}
|
|
/>
|
|
</div>
|
|
</nav>
|
|
</aside>
|
|
{/if}
|
|
</header>
|
|
|
|
<slot />
|
|
|
|
<!-- Mobile navigation -->
|
|
<nav
|
|
class="sticky bottom-0 z-10 flex h-14 flex-row items-center justify-around border-t-2 border-contrast-100 bg-primary-100 px-2 text-xs shadow-t-lg sm:hidden"
|
|
>
|
|
{#each Routes.topbarRoutes as route}
|
|
<a
|
|
href={route.url}
|
|
target={route.target}
|
|
class={`flex flex-col items-center decoration-accent transition-opacity ${
|
|
isCurrentPath(route.url)
|
|
? "underline opacity-100"
|
|
: "opacity-50"
|
|
}`}
|
|
>
|
|
<img src={route.icon} alt={route.text} class="h-6 dark:invert" />
|
|
<span> {route.text} </span>
|
|
</a>
|
|
{/each}
|
|
</nav>
|
|
|
|
<style>
|
|
.hamburger-icon.open .line:first-child {
|
|
transform: rotate(45deg) translateX(15%);
|
|
}
|
|
|
|
.hamburger-icon.open .line:last-child {
|
|
transform: rotate(-45deg) translateX(15%);
|
|
}
|
|
|
|
.hamburger-icon.open .line.middle {
|
|
width: 0;
|
|
transition: transform 0.1s;
|
|
}
|
|
</style>
|