Browse Source

Add collapsible left menu to navbar

master
buttercat1791 2 years ago committed by Silberengel
parent
commit
a043e33909
  1. 75
      src/lib/Article.svelte
  2. 10
      src/lib/components/Navigation.svelte
  3. 5
      src/lib/stores.ts

75
src/lib/Article.svelte

@ -1,11 +1,10 @@ @@ -1,11 +1,10 @@
<script lang="ts">
import { ndk } from '$lib/ndk';
import { idList } from '$lib/stores';
import { idList, isLeftHamburgerMenuInUse, leftHamburgerMenuHrefs, leftHamburgerMenuItems } from '$lib/stores';
import type { NDKEvent } from '@nostr-dev-kit/ndk';
import { page } from '$app/stores';
import { Heading, Sidebar, SidebarGroup, SidebarItem, SidebarWrapper, Skeleton, TextPlaceholder } from 'flowbite-svelte';
import showdown from 'showdown';
import { sineIn } from 'svelte/easing';
import { onMount } from 'svelte';
$: activeHash = $page.url.hash;
@ -13,7 +12,25 @@ @@ -13,7 +12,25 @@
async function getEvents(): Promise<NDKEvent[]> {
const eventPromises = $idList.map(async (id) => await $ndk.fetchEvent(id));
const events = await Promise.all(eventPromises);
return events.filter((event) => event != null);
const filteredEvents = events.filter((event) => event != null);
const eventNames: string[] = [];
const eventHrefs = new Map<string, string>();
filteredEvents.forEach(event => {
const title = event.getMatchingTags('title')[0][1];
eventNames.push(title);
const normalizedTitle = normalizeHashPath(title);
eventHrefs.set(title, `${$page.url.pathname}#${normalizedTitle}`);
});
leftHamburgerMenuItems.set(eventNames);
leftHamburgerMenuHrefs.set(eventHrefs);
return filteredEvents;
}
function normalizeHashPath(str: string): string {
@ -40,13 +57,21 @@ @@ -40,13 +57,21 @@
}
}
const sidebarBreakpointWidth = 1140;
const setLeftHamburgerMenuInUse = () => {
isLeftHamburgerMenuInUse.set(window.innerWidth < sidebarBreakpointWidth ? true : false);
};
onMount(() => {
window.addEventListener('hashchange', scrollToElementWithOffset);
// Also handle the case where the user lands on the page with a hash in the URL
scrollToElementWithOffset();
window.addEventListener('resize', setLeftHamburgerMenuInUse);
return () => {
window.removeEventListener('hashchange', scrollToElementWithOffset);
window.removeEventListener('resize', setLeftHamburgerMenuInUse);
};
});
@ -54,28 +79,30 @@ @@ -54,28 +79,30 @@
</script>
{#await getEvents()}
<Sidebar class='sidebar-leather fixed top-20 left-0 px-4 w-60'>
<SidebarWrapper>
<Skeleton/>
</SidebarWrapper>
</Sidebar>
<TextPlaceholder class='max-w-2xl'/>
{#if !$isLeftHamburgerMenuInUse}
<Sidebar class='sidebar-leather fixed top-20 left-0 px-4 w-60'>
<SidebarWrapper>
<Skeleton/>
</SidebarWrapper>
</Sidebar>
<TextPlaceholder class='max-w-2xl'/>
{/if}
{:then events}
<!-- TODO: Collapse the sidebar when the page gets below a certain width. -->
<!-- TODO: Handle hash paths for navigation within the article. -->
<Sidebar class='sidebar-leather fixed top-20 left-0 px-4 w-60' {activeHash}>
<SidebarWrapper>
<SidebarGroup class='sidebar-group-leather overflow-y-scroll'>
{#each events as event}
<SidebarItem
class='sidebar-item-leather'
label={event.getMatchingTags('title')[0][1]}
href={`${$page.url.pathname}#${normalizeHashPath(event.getMatchingTags('title')[0][1])}`}
/>
{/each}
</SidebarGroup>
</SidebarWrapper>
</Sidebar>
{#if !$isLeftHamburgerMenuInUse}
<Sidebar class='sidebar-leather fixed top-20 left-0 px-4 w-60' {activeHash}>
<SidebarWrapper>
<SidebarGroup class='sidebar-group-leather overflow-y-scroll'>
{#each events as event}
<SidebarItem
class='sidebar-item-leather'
label={event.getMatchingTags('title')[0][1]}
href={`${$page.url.pathname}#${normalizeHashPath(event.getMatchingTags('title')[0][1])}`}
/>
{/each}
</SidebarGroup>
</SidebarWrapper>
</Sidebar>
{/if}
<div class='flex flex-col space-y-4 max-w-2xl'>
{#each events as event}
<div class='note-leather flex flex-col space-y-2'>

10
src/lib/components/Navigation.svelte

@ -1,11 +1,21 @@ @@ -1,11 +1,21 @@
<script lang="ts">
import { isLeftHamburgerMenuInUse, leftHamburgerMenuHrefs, leftHamburgerMenuItems } from '$lib/stores';
import { DarkMode, Navbar, NavLi, NavUl, NavHamburger, NavBrand } from 'flowbite-svelte';
import { get } from 'svelte/store';
let className: string;
export { className as class };
</script>
<Navbar class={`Navbar navbar-leather ${className}`}>
{#if $isLeftHamburgerMenuInUse}
<NavHamburger class='btn-leather' />
<NavUl class='ul-leather'>
{#each $leftHamburgerMenuItems as menuItem}
<NavLi href={$leftHamburgerMenuHrefs.get(menuItem)}>{menuItem}</NavLi>
{/each}
</NavUl>
{/if}
<div class='flex flex-grow justify-between'>
<NavBrand href='./'>
<h1 class='font-serif'>Alexandria</h1>

5
src/lib/stores.ts

@ -1,3 +1,8 @@ @@ -1,3 +1,8 @@
import { writable } from "svelte/store";
export let idList = writable<string[]>([]);
export const isLeftHamburgerMenuInUse = writable(false);
export const leftHamburgerMenuItems = writable<string[]>([]);
export const leftHamburgerMenuHrefs = writable<Map<string, string>>(new Map());

Loading…
Cancel
Save