basic left,right layout

This commit is contained in:
Jacky Zhao 2023-06-17 14:36:06 -07:00
parent ad8ac0b479
commit de72a413ba
9 changed files with 73 additions and 33 deletions

View File

@ -59,15 +59,16 @@ const config: QuartzConfig = {
Plugin.ContentPage({ Plugin.ContentPage({
head: Component.Head(), head: Component.Head(),
header: [Component.PageTitle(), Component.Spacer(), Component.Darkmode()], header: [Component.PageTitle(), Component.Spacer(), Component.Darkmode()],
body: [ beforeBody: [
Component.ArticleTitle(), Component.ArticleTitle(),
Component.ReadingTime(), Component.ReadingTime(),
Component.TagList(), Component.TagList(),
Component.TableOfContents(),
Component.Content()
], ],
left: [], left: [
right: [], Component.TableOfContents(),
],
right: [
],
footer: [] footer: []
}), }),
Plugin.ContentIndex(), // you can exclude this if you don't plan on using popovers, graph, or backlinks, Plugin.ContentIndex(), // you can exclude this if you don't plan on using popovers, graph, or backlinks,

View File

@ -6,7 +6,7 @@ function TagList({ fileData }: QuartzComponentProps) {
const tags = fileData.frontmatter?.tags const tags = fileData.frontmatter?.tags
const slug = fileData.slug! const slug = fileData.slug!
const baseDir = resolveToRoot(slug) const baseDir = resolveToRoot(slug)
if (tags) { if (tags && tags.length > 0) {
return <ul class="tags">{tags.map(tag => { return <ul class="tags">{tags.map(tag => {
const display = `#${tag}` const display = `#${tag}`
const linkDest = baseDir + `/tags/${slugAnchor(tag)}` const linkDest = baseDir + `/tags/${slugAnchor(tag)}`

View File

@ -6,19 +6,21 @@ function toggleCallout(this: HTMLElement) {
outerBlock.style.maxHeight = height + `px` outerBlock.style.maxHeight = height + `px`
} }
function setupCallout(div: HTMLElement) { function setupCallout() {
const collapsed = div.classList.contains(`is-collapsed`)
const title = div.firstElementChild!
const height = collapsed ? title.scrollHeight : div.scrollHeight
div.style.maxHeight = height + `px`
}
document.addEventListener(`nav`, () => {
const collapsible = document.getElementsByClassName(`callout is-collapsible`) as HTMLCollectionOf<HTMLElement> const collapsible = document.getElementsByClassName(`callout is-collapsible`) as HTMLCollectionOf<HTMLElement>
for (const div of collapsible) { for (const div of collapsible) {
const title = div.firstElementChild const title = div.firstElementChild
setupCallout(div)
title?.removeEventListener(`click`, toggleCallout) if (title) {
title?.addEventListener(`click`, toggleCallout) title.removeEventListener(`click`, toggleCallout)
title.addEventListener(`click`, toggleCallout)
const collapsed = div.classList.contains(`is-collapsed`)
const height = collapsed ? title.scrollHeight : div.scrollHeight
div.style.maxHeight = height + `px`
}
} }
}) }
document.addEventListener(`nav`, setupCallout)
window.addEventListener(`resize`, setupCallout)

View File

@ -14,19 +14,24 @@ const observer = new IntersectionObserver(entries => {
} }
}) })
function toggleCollapsible(this: HTMLElement) { function toggleToc(this: HTMLElement) {
this.classList.toggle("collapsed") this.classList.toggle("collapsed")
const content = this.nextElementSibling as HTMLElement const content = this.nextElementSibling as HTMLElement
content.classList.toggle("collapsed") content.classList.toggle("collapsed")
content.style.maxHeight = content.style.maxHeight === "0px" ? content.scrollHeight + "px" : "0px" content.style.maxHeight = content.style.maxHeight === "0px" ? content.scrollHeight + "px" : "0px"
} }
document.addEventListener("nav", () => { function setupToc() {
const toc = document.getElementById("toc")! const toc = document.getElementById("toc")!
const content = toc.nextElementSibling as HTMLElement const content = toc.nextElementSibling as HTMLElement
content.style.maxHeight = content.scrollHeight + "px" content.style.maxHeight = content.scrollHeight + "px"
toc.removeEventListener("click", toggleCollapsible) toc.removeEventListener("click", toggleToc)
toc.addEventListener("click", toggleCollapsible) toc.addEventListener("click", toggleToc)
}
window.addEventListener("resize", setupToc)
document.addEventListener("nav", () => {
setupToc()
// update toc entry highlighting // update toc entry highlighting
observer.disconnect() observer.disconnect()

View File

@ -4,10 +4,6 @@
min-width: 30px; min-width: 30px;
position: relative; position: relative;
@media all and (max-width: 450px) {
padding: 1rem;
}
& > .toggle { & > .toggle {
display: none; display: none;
box-sizing: border-box; box-sizing: border-box;

View File

@ -6,11 +6,12 @@ import { resolveToRoot } from "../../path"
import HeaderConstructor from "../../components/Header" import HeaderConstructor from "../../components/Header"
import { QuartzComponentProps } from "../../components/types" import { QuartzComponentProps } from "../../components/types"
import BodyConstructor from "../../components/Body" import BodyConstructor from "../../components/Body"
import ContentConstructor from "../../components/Content"
interface Options { interface Options {
head: QuartzComponent head: QuartzComponent
header: QuartzComponent[], header: QuartzComponent[],
body: QuartzComponent[], beforeBody: QuartzComponent[],
left: QuartzComponent[], left: QuartzComponent[],
right: QuartzComponent[], right: QuartzComponent[],
footer: QuartzComponent[], footer: QuartzComponent[],
@ -21,14 +22,15 @@ export const ContentPage: QuartzEmitterPlugin<Options> = (opts) => {
throw new Error("ContentPage must be initialized with options specifiying the components to use") throw new Error("ContentPage must be initialized with options specifiying the components to use")
} }
const { head: Head, header, body } = opts const { head: Head, header, beforeBody, left, right, footer } = opts
const Header = HeaderConstructor() const Header = HeaderConstructor()
const Body = BodyConstructor() const Body = BodyConstructor()
const Content = ContentConstructor()
return { return {
name: "ContentPage", name: "ContentPage",
getQuartzComponents() { getQuartzComponents() {
return [opts.head, Header, Body, ...opts.header, ...opts.body, ...opts.left, ...opts.right, ...opts.footer] return [opts.head, Header, Body, ...opts.header, ...opts.beforeBody, ...opts.left, ...opts.right, ...opts.footer]
}, },
async emit(_contentDir, cfg, content, resources, emit): Promise<string[]> { async emit(_contentDir, cfg, content, resources, emit): Promise<string[]> {
const fps: string[] = [] const fps: string[] = []
@ -59,9 +61,19 @@ export const ContentPage: QuartzEmitterPlugin<Options> = (opts) => {
<Header {...componentData} > <Header {...componentData} >
{header.map(HeaderComponent => <HeaderComponent {...componentData} />)} {header.map(HeaderComponent => <HeaderComponent {...componentData} />)}
</Header> </Header>
{beforeBody.map(BodyComponent => <BodyComponent {...componentData} />)}
<Body {...componentData}> <Body {...componentData}>
{body.map(BodyComponent => <BodyComponent {...componentData} />)} <div class="left">
{left.map(BodyComponent => <BodyComponent {...componentData} />)}
</div>
<div class="center">
<Content {...componentData} />
</div>
<div class="right">
{right.map(BodyComponent => <BodyComponent {...componentData} />)}
</div>
</Body> </Body>
</div> </div>
</body> </body>
{pageResources.js.filter(resource => resource.loadTime === "afterDOMReady").map(res => JSResourceToScriptElement(res))} {pageResources.js.filter(resource => resource.loadTime === "afterDOMReady").map(res => JSResourceToScriptElement(res))}

View File

@ -300,8 +300,6 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>
}) })
} }
console.log(js)
return { js } return { js }
} }
} }

View File

@ -51,8 +51,31 @@ a {
padding: 4rem 30vw; padding: 4rem 30vw;
margin: 0 auto; margin: 0 auto;
max-width: 1000px; max-width: 1000px;
position: relative;
& .left, & .right {
position: fixed;
padding: 0 4rem 0 6rem;
max-width: 30vw;
box-sizing: border-box;
top: 10rem;
}
& .left {
left: 0;
}
& .right {
right: 0;
}
@media all and (max-width: 1200px) { @media all and (max-width: 1200px) {
padding: 25px 5vw; padding: 25px 5vw;
& .left, & .right {
padding: 0;
max-width: none;
position: initial;
}
} }
& p { & p {

View File

@ -8,6 +8,10 @@
overflow-y: hidden; overflow-y: hidden;
transition: max-height 0.3s ease; transition: max-height 0.3s ease;
& > *:nth-child(2) {
margin-top: 0;
}
&[data-callout="note"] { &[data-callout="note"] {
--color: #448aff; --color: #448aff;
--border: #448aff22; --border: #448aff22;
@ -74,7 +78,6 @@
align-items: center; align-items: center;
gap: 5px; gap: 5px;
padding: 1rem 0; padding: 1rem 0;
margin-bottom: -1rem;
color: var(--color); color: var(--color);
& .fold { & .fold {