field-guide / src /lib /components /Nav.svelte
pngwn
improve submissions docs
a8647ab
<script lang="ts">
import { page } from '$app/state';
import { NAV } from '$lib/data/content';
import StampBadge from './StampBadge.svelte';
import Icon from './Icon.svelte';
interface Props {
active?: string;
}
let { active = 'top' }: Props = $props();
let open = $state(false);
const close = () => (open = false);
// On the home page the section links are plain fragments; from any other
// route they point back to the home page's anchors. "submit" is now its own
// route, so it always links there.
const onHome = $derived(page.url.pathname === '/');
const linkFor = (id: string) =>
id === 'submit' ? '/submit' : onHome ? `#${id}` : `/#${id}`;
// close the popout on Escape, and when the viewport grows back to the wide layout
$effect(() => {
if (!open) return;
const onKey = (e: KeyboardEvent) => {
if (e.key === 'Escape') close();
};
const onResize = () => {
if (window.innerWidth > 1000) close();
};
window.addEventListener('keydown', onKey);
window.addEventListener('resize', onResize);
return () => {
window.removeEventListener('keydown', onKey);
window.removeEventListener('resize', onResize);
};
});
</script>
<nav class="nav">
<div class="wrap nav__inner">
<a href={onHome ? '#top' : '/'} class="nav__brand" onclick={close}>
<StampBadge glyph="trees" accent="var(--forest)" size={32} spin={false} />
<span class="display nav__brand-text">Build Small</span>
</a>
<div class="nav__links">
{#each NAV as n (n.id)}
<a href={linkFor(n.id)} class="nav__link" data-active={active === n.id}>{n.label}</a>
{/each}
</div>
<button
class="nav__toggle"
aria-label={open ? 'Close menu' : 'Open menu'}
aria-expanded={open}
aria-controls="nav-menu"
onclick={() => (open = !open)}
>
<Icon name={open ? 'close' : 'menu'} size={22} stroke="var(--ink)" />
</button>
<a class="btn btn--accent nav__submit" href="/submit" onclick={close}>
Submit <Icon name="arrow" size={15} stroke="#fff" />
</a>
</div>
{#if open}
<!-- click-away scrim -->
<button class="nav__scrim" aria-hidden="true" tabindex="-1" onclick={close}></button>
<div class="nav__menu" id="nav-menu">
{#each NAV as n (n.id)}
<a
href={linkFor(n.id)}
class="nav__menu-link"
data-active={active === n.id}
onclick={close}>{n.label}</a
>
{/each}
</div>
{/if}
</nav>