feat: add toc header on mobile instead of card

This commit is contained in:
Youwen Wu 2024-04-07 02:25:34 -07:00
parent e604f0f6af
commit 0c8370ee8a
Signed by: youwen5
GPG key ID: 865658ED1FE61EC3
5 changed files with 67 additions and 35 deletions

View file

@ -8,7 +8,7 @@
import ThemePicker from '../ThemePicker.svelte'; import ThemePicker from '../ThemePicker.svelte';
</script> </script>
<Drawer.Root shouldScaleBackground direction="top"> <Drawer.Root direction="top">
<Drawer.Trigger asChild let:builder> <Drawer.Trigger asChild let:builder>
<Button variant="outline" size="icon" builders={[builder]} class="px-2 md:hidden"> <Button variant="outline" size="icon" builders={[builder]} class="px-2 md:hidden">
<HamburgerMenu class="icon border-1 border-primary" /> <HamburgerMenu class="icon border-1 border-primary" />

View file

@ -0,0 +1,56 @@
<script lang="ts">
import type { TocStore } from '@svelte-put/toc';
import Separator from '../ui/separator/separator.svelte';
import { Accordion } from 'bits-ui';
import { toclink } from '@svelte-put/toc';
import { CaretDown } from 'svelte-radix';
import { slide } from 'svelte/transition';
export let tocStore: TocStore;
export let placeholder: string;
const calcTextClasses = (el: HTMLElement) => {
if (el.tagName === 'H2') return 'text-xl';
return 'text-md text-muted-foreground';
};
$: currentDisplayed = $tocStore.activeItem ? $tocStore.activeItem.text : placeholder;
</script>
<nav class="fixed top-24 left-0 w-full bg-background bg-opacity-50 backdrop-blur-lg z-30 lg:hidden">
<Accordion.Root class="px-8">
<Accordion.Item value="toc">
<Accordion.Trigger
class="text-xl flex w-full flex-1 items-center justify-between py-1 font-medium transition-all [&[data-state=open]>span>svg]:rotate-180"
>{currentDisplayed}
<span
class="inline-flex size-8 items-center justify-center rounded-[7px] bg-transparent transition-all hover:bg-dark-10"
><CaretDown class="size-[18px] transition-all duration-200" /></span
>
</Accordion.Trigger>
<Accordion.Content transition={slide} transitionConfig={{ duration: 200 }} class="pb-[25px]">
{#if $tocStore.items.size}
<ol>
{#each $tocStore.items.values() as tocItem}
{@const selected = $tocStore.activeItem === tocItem}
<li class="border-l-secondary border-l-4 py-1" class:highlighted={selected}>
<!-- svelte-ignore a11y-missing-attribute a11y-missing-content -->
<a
use:toclink={{ store: tocStore, tocItem, observe: true }}
class={`hover:bg-muted px-2 py-1 rounded-r-sm transition-all ${calcTextClasses(tocItem.element)}`}
/>
</li>
{/each}
</ol>
{/if}
</Accordion.Content>
</Accordion.Item>
</Accordion.Root>
<Separator />
</nav>
<style lang="postcss">
.highlighted {
@apply bg-blue-200 dark:bg-blue-900 border-l-blue-500;
}
</style>

View file

@ -1,27 +1 @@
import type { PageLoad } from './$types.js';
import { marked } from 'marked';
import markedKatex from 'marked-katex-extension';
import markedAlert from 'marked-alert';
export const prerender = true; export const prerender = true;
const options = {
throwOnError: false
};
marked.use(markedKatex(options));
marked.use(markedAlert());
export const load: PageLoad = async ({ fetch }) => {
try {
const data = await fetch('/test.md');
const markdown = await marked.parse(await data.text());
return {
markdown
};
} catch (e) {
return {
markdown: `Error: ${e}`
};
}
};

View file

@ -1,9 +1,10 @@
<script lang="ts"> <script lang="ts">
import MobileToc from '$lib/components/Toc/MobileToc.svelte';
import type { PageData } from './$types'; import type { PageData } from './$types';
import Article from '$lib/components/Blog/Article.svelte'; import Article from '$lib/components/Blog/Article.svelte';
import { toc, createTocStore } from '@svelte-put/toc'; import { toc, createTocStore } from '@svelte-put/toc';
import StickyToc from '$lib/components/Toc/StickyToc.svelte'; import StickyToc from '$lib/components/Toc/StickyToc.svelte';
import TocHeader from '$lib/components/toc/TocHeader.svelte';
const tocStore = createTocStore(); const tocStore = createTocStore();
export let data: PageData; export let data: PageData;
@ -28,7 +29,9 @@
<meta name="author" content="Youwen Wu" /> <meta name="author" content="Youwen Wu" />
</svelte:head> </svelte:head>
<div class="lg:flex mx-auto mt-14 px-4"> <TocHeader {tocStore} placeholder="On this page" />
<div class="lg:flex mx-auto mt-24 lg:mt-14 px-4">
<div class="flex-shrink xl:basis-1/4" /> <div class="flex-shrink xl:basis-1/4" />
<main <main
class="flex-grow basis-3/4 xl:basis-2/4 flex-shrink" class="flex-grow basis-3/4 xl:basis-2/4 flex-shrink"
@ -39,14 +42,11 @@
properties: { 'aria-hidden': 'true', class: 'hidden' }, properties: { 'aria-hidden': 'true', class: 'hidden' },
position: 'before' position: 'before'
}, },
scrollMarginTop: 120 scrollMarginTop: 120,
selector: ':where(h2, h3, h4, h5, h6)'
}} }}
> >
<Article {doc}> <Article {doc} />
<svelte:fragment slot="mobile-toc">
<MobileToc {tocStore} />
</svelte:fragment>
</Article>
</main> </main>
<aside class="basis-1/4 relative hidden lg:block"> <aside class="basis-1/4 relative hidden lg:block">

View file

@ -1,3 +1,5 @@
## Introduction
The following content is a test post for the blog's markdown and $\KaTeX$ rendering capabilities. There's a few errors, and wikilinks aren't supported. This file was copy pasted directly out of my `obsidian.md` notebook, so it contains some weird formatting. The following content is a test post for the blog's markdown and $\KaTeX$ rendering capabilities. There's a few errors, and wikilinks aren't supported. This file was copy pasted directly out of my `obsidian.md` notebook, so it contains some weird formatting.
<br /> <br />