mirror of
https://github.com/youwen5/site.git
synced 2024-11-24 17:33:51 -08:00
feat: add toc header on mobile instead of card
This commit is contained in:
parent
e604f0f6af
commit
0c8370ee8a
5 changed files with 67 additions and 35 deletions
|
@ -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" />
|
||||||
|
|
56
src/lib/components/Toc/TocHeader.svelte
Normal file
56
src/lib/components/Toc/TocHeader.svelte
Normal 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>
|
|
@ -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}`
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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 />
|
||||||
|
|
Loading…
Reference in a new issue