Browse Source

Handle in-article hash path navigation

master
buttercat1791 2 years ago committed by Silberengel
parent
commit
99d9943e26
  1. 79
      src/lib/Article.svelte

79
src/lib/Article.svelte

@ -16,25 +16,41 @@
return events.filter((event) => event != null); return events.filter((event) => event != null);
} }
const converter = new showdown.Converter(); function normalizeHashPath(str: string): string {
return str
.toLowerCase()
.replace(/\s+/g, '-')
.replace(/[^\w-]/g, '');
}
const transitionParams = { function scrollToElementWithOffset() {
x: -320, const hash = window.location.hash;
duration: 200, if (hash) {
easing: sineIn const targetElement = document.querySelector(hash);
}; if (targetElement) {
const headerOffset = 80;
const elementPosition = targetElement.getBoundingClientRect().top;
const offsetPosition = elementPosition + window.scrollY - headerOffset;
window.scrollTo({
top: offsetPosition,
behavior: 'auto',
});
}
}
}
let width: number;
let breakpoint: number = 768; // Tailwind md breakpoint
let drawerHidden: boolean = false;
$: width >= breakpoint
? drawerHidden = false
: drawerHidden = true;
onMount(() => { onMount(() => {
width >= breakpoint window.addEventListener('hashchange', scrollToElementWithOffset);
? drawerHidden = false // Also handle the case where the user lands on the page with a hash in the URL
: drawerHidden = true; scrollToElementWithOffset();
return () => {
window.removeEventListener('hashchange', scrollToElementWithOffset);
};
}); });
const converter = new showdown.Converter();
</script> </script>
{#await getEvents()} {#await getEvents()}
@ -49,12 +65,12 @@
<!-- TODO: Handle hash paths for navigation within the article. --> <!-- TODO: Handle hash paths for navigation within the article. -->
<Sidebar class='sidebar-leather fixed top-20 left-0 px-4 w-60' {activeHash}> <Sidebar class='sidebar-leather fixed top-20 left-0 px-4 w-60' {activeHash}>
<SidebarWrapper> <SidebarWrapper>
<SidebarGroup> <SidebarGroup class='sidebar-group-leather overflow-y-scroll'>
{#each events as event} {#each events as event}
<SidebarItem <SidebarItem
class='sidebar-item-leather' class='sidebar-item-leather'
label={event.getMatchingTags('title')[0][1]} label={event.getMatchingTags('title')[0][1]}
href={`${$page.url.pathname}#${event.getMatchingTags('title')[0][1]}`} href={`${$page.url.pathname}#${normalizeHashPath(event.getMatchingTags('title')[0][1])}`}
/> />
{/each} {/each}
</SidebarGroup> </SidebarGroup>
@ -63,7 +79,13 @@
<div class='flex flex-col space-y-4 max-w-2xl'> <div class='flex flex-col space-y-4 max-w-2xl'>
{#each events as event} {#each events as event}
<div class='note-leather flex flex-col space-y-2'> <div class='note-leather flex flex-col space-y-2'>
<Heading tag='h3' class='h-leather'>{event.getMatchingTags('title')[0][1]}</Heading> <Heading
tag='h3'
class='h-leather'
id={normalizeHashPath(event.getMatchingTags('title')[0][1])}
>
{event.getMatchingTags('title')[0][1]}
</Heading>
{@html converter.makeHtml(event.content)} {@html converter.makeHtml(event.content)}
</div> </div>
{/each} {/each}
@ -71,24 +93,7 @@
{/await} {/await}
<style> <style>
.article { :global(.sidebar-group-leather) {
display: flex; max-height: calc(100vh - 8rem);
padding: 1rem;
}
.toc {
padding: 3%;
min-width: 5%;
padding-top: 1%;
border: 1px white solid;
border-radius: 10px;
border-top-width: 5px;
}
.article-content {
min-width: 80%;
max-width: 85%;
padding: 1%;
border: 1px white solid;
border-radius: 10px;
border-top-width: 5px;
} }
</style> </style>

Loading…
Cancel
Save