wip toc
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
Michael Zhang 2023-09-01 12:38:59 -05:00
parent e94fee5345
commit 3bf0200e7e
7 changed files with 138 additions and 39 deletions

View file

@ -0,0 +1,41 @@
---
import type { MarkdownHeading } from "astro";
import "../styles/toc.scss";
interface Props {
toc: boolean;
headings: MarkdownHeading[];
}
const { toc, headings } = Astro.props;
---
{
toc ? (
<>
<div class="toc-wrapper">
<slot />
<div class="toc">
Table of contents
<ul>
{headings.map((heading) => {
return (
<li>
<a href={`#${heading.slug}`}>{heading.text}</a>
</li>
);
})}
</ul>
</div>
</div>
</>
) : (
<slot />
)
}
<script type="text/javascript">
document.addEventListener("scroll", (doc, evt) => {
console.log("SHIET");
});
</script>

View file

@ -27,6 +27,7 @@ const posts = defineCollection({
tags: z.array(z.string()),
draft: z.boolean().default(false),
math: z.boolean().default(false),
toc: z.boolean().default(false),
}),
});

View file

@ -11,6 +11,7 @@ tags:
heroImage: ./header.jpg
heroAlt: gears spinning wallpaper
math: true
toc: true
---
Back in 2022, I took a special topics course, CSCI 8980, on [reasoning about

View file

@ -4,6 +4,7 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
import { type CollectionEntry, getCollection } from "astro:content";
import Timestamp from "../../components/Timestamp.astro";
import { getImage } from "astro:assets";
import TocWrapper from "../../components/TocWrapper.astro";
export async function getStaticPaths() {
const posts = await getCollection("posts");
@ -16,8 +17,8 @@ export async function getStaticPaths() {
type Props = CollectionEntry<"posts">;
const post = Astro.props;
const { Content, remarkPluginFrontmatter } = await post.render();
const { heroImage: heroImagePath, heroAlt } = post.data;
const { Content, remarkPluginFrontmatter, headings } = await post.render();
const { toc, heroImage: heroImagePath, heroAlt } = post.data;
let heroImage;
if (heroImagePath) {
@ -44,44 +45,44 @@ const datestamp = post.data.date.toLocaleDateString(undefined, {
<meta slot="head" property="article:published_time" content={datestamp} />
<meta slot="head" property="article:author" content="Michael Zhang" />
<div class="post-container">
<h1 class="post-title">{post.data.title}</h1>
<TocWrapper toc={toc} headings={headings}>
<div class="post-container">
<h1 class="post-title">{post.data.title}</h1>
<span class="tags">
{
post.data.draft && (
<a href="/drafts" class="tag draft">
<i class="fa fa-warning" aria-hidden="true" />
<span class="text">draft</span>
</a>
)
}
{
post.data.tags.map((tag) => (
<a href={`/tags/${tag}`} class="tag">
<i class="fa fa-tag" aria-hidden="true" />
<span class="text">{tag}</span>
</a>
))
}
</span>
<small class="post-meta">
Posted on <Timestamp timestamp={post.data.date} />
- {remarkPluginFrontmatter.minutesRead}
</small>
<span class="tags">
{
post.data.draft && (
<a href="/drafts" class="tag draft">
<i class="fa fa-warning" aria-hidden="true" />
<span class="text">draft</span>
</a>
heroImage && heroAlt && (
<div style={`background-image: url(${heroImage.src});`} title={heroAlt} class="hero" />
)
}
{
post.data.tags.map((tag) => (
<a href={`/tags/${tag}`} class="tag">
<i class="fa fa-tag" aria-hidden="true" />
<span class="text">{tag}</span>
</a>
))
}
</span>
<small class="post-meta">
Posted on <Timestamp timestamp={post.data.date} />
- {remarkPluginFrontmatter.minutesRead}
</small>
{
heroImage && heroAlt && (
<div style={`background-image: url(${heroImage.src});`} title={heroAlt} class="hero" />
)
}
<!-- <BlogPost {...post.data}> -->
<div class="post-content">
<Content />
<div class="post-content">
<Content />
</div>
</div>
</div>
<!-- </BlogPost> -->
</TocWrapper>
</BaseLayout>

View file

@ -12,7 +12,6 @@ body {
background-color: var(--background-color);
color: var(--text-color);
max-width: 1024px;
margin: auto;
width: 100%;
height: 1px;
@ -94,12 +93,13 @@ pre > code {
display: flex;
flex-direction: row;
align-items: stretch;
justify-content: center;
}
.flex-wrapper > main {
min-width: 0;
box-sizing: border-box;
padding: 20px;
// padding: 20px;
}
@media screen and (max-width: variables.$breakpoint) {
@ -120,6 +120,6 @@ pre > code {
}
.flex-wrapper > main {
padding-left: 30px;
// padding-left: 30px;
}
}

View file

@ -1,3 +1,5 @@
@use "variables";
.post-title {
font-size: 2rem;
font-weight: 600;
@ -20,7 +22,9 @@
}
.post-container {
max-width: 720px;
display: flex;
padding: 20px;
flex-direction: column;
.toc-drawer {
@ -175,6 +179,12 @@
}
}
@media screen and (min-width: variables.$breakpoint) {
.post-container {
padding-left: 30px;
}
}
.division .post-content,
.post-content {
.heading {
@ -210,6 +220,7 @@ hr.endline {
display: flex;
gap: 6px;
margin-bottom: 6px;
flex-wrap: wrap;
.tag {
font-size: 0.75rem;

44
src/styles/toc.scss Normal file
View file

@ -0,0 +1,44 @@
@use "variables";
$tocWidth: 180px;
$tocBreakpoint: variables.$breakpoint + $tocWidth;
.toc-wrapper {
position: relative;
display: flex;
}
.toc {
height: 100vh;
ul {
list-style-type: none;
padding-inline-start: 0;
li {
font-size: 14px;
}
}
}
@media screen and (max-width: $tocBreakpoint) {
.toc {
display: none;
}
}
@media screen and (min-width: $tocBreakpoint) {
.article {
flex-grow: 1;
}
.toc {
flex: 0 0 $tocWidth;
max-width: $tocWidth;
position: sticky;
top: 0;
padding: 20px;
overflow-y: auto;
}
}