From a190cba737f223d8245bd5632bc7a653800dc1be Mon Sep 17 00:00:00 2001 From: saberzero1 Date: Tue, 1 Oct 2024 22:12:17 +0200 Subject: [PATCH 01/23] Rewrite mobile explorer --- quartz.layout.ts | 2 +- quartz/components/Explorer.tsx | 111 ++++-- quartz/components/ExplorerNode.tsx | 4 +- quartz/components/scripts/explorer.inline.ts | 177 +++++++--- quartz/components/styles/explorer.scss | 353 ++++++++++++------- 5 files changed, 430 insertions(+), 217 deletions(-) diff --git a/quartz.layout.ts b/quartz.layout.ts index 4a78256a..ab4c0c84 100644 --- a/quartz.layout.ts +++ b/quartz.layout.ts @@ -27,7 +27,7 @@ export const defaultContentPageLayout: PageLayout = { Component.MobileOnly(Component.Spacer()), Component.Search(), Component.Darkmode(), - Component.DesktopOnly(Component.Explorer()), + Component.Explorer(), ], right: [ Component.Graph(), diff --git a/quartz/components/Explorer.tsx b/quartz/components/Explorer.tsx index ec7c48ef..ea43815e 100644 --- a/quartz/components/Explorer.tsx +++ b/quartz/components/Explorer.tsx @@ -5,7 +5,6 @@ import explorerStyle from "./styles/explorer.scss" import script from "./scripts/explorer.inline" import { ExplorerNode, FileNode, Options } from "./ExplorerNode" import { QuartzPluginData } from "../plugins/vfile" -import { classNames } from "../util/lang" import { i18n } from "../i18n" // Options interface defined in `ExplorerNode` to avoid circular dependency @@ -13,6 +12,7 @@ const defaultOptions = { folderClickBehavior: "collapse", folderDefaultState: "collapsed", useSavedState: true, + usePagePath: false, mapFn: (node) => { return node }, @@ -46,7 +46,7 @@ export default ((userOpts?: Partial) => { let jsonTree: string let lastBuildId: string = "" - function constructFileTree(allFiles: QuartzPluginData[]) { + function constructFileTree(allFiles: QuartzPluginData[], currentFilePath: string) { // Construct tree from allFiles fileTree = new FileNode("") allFiles.forEach((file) => fileTree.add(file)) @@ -68,7 +68,10 @@ export default ((userOpts?: Partial) => { // Get all folders of tree. Initialize with collapsed state // Stringify to pass json tree as data attribute ([data-tree]) - const folders = fileTree.getFolderPaths(opts.folderDefaultState === "collapsed") + const folders = fileTree.getFolderPaths( + opts.folderDefaultState === "collapsed", + currentFilePath, + ) jsonTree = JSON.stringify(folders) } @@ -81,42 +84,78 @@ export default ((userOpts?: Partial) => { }: QuartzComponentProps) => { if (ctx.buildId !== lastBuildId) { lastBuildId = ctx.buildId - constructFileTree(allFiles) + constructFileTree(allFiles, (fileData.filePath ?? "").replaceAll(" ", "-")) } - return ( -
- + +
+
+ -
-
    - -
  • -
+

{opts.title ?? i18n(cfg.locale).components.explorer.title}

+ + + + +
+
    + +
  • +
+
) diff --git a/quartz/components/ExplorerNode.tsx b/quartz/components/ExplorerNode.tsx index e57d6771..88246e04 100644 --- a/quartz/components/ExplorerNode.tsx +++ b/quartz/components/ExplorerNode.tsx @@ -16,6 +16,7 @@ export interface Options { folderDefaultState: "collapsed" | "open" folderClickBehavior: "collapse" | "link" useSavedState: boolean + usePagePath: boolean sortFn: (a: FileNode, b: FileNode) => number filterFn: (node: FileNode) => boolean mapFn: (node: FileNode) => void @@ -124,9 +125,10 @@ export class FileNode { * Get folder representation with state of tree. * Intended to only be called on root node before changes to the tree are made * @param collapsed default state of folders (collapsed by default or not) + * @param currentFile current file * @returns array containing folder state for tree */ - getFolderPaths(collapsed: boolean): FolderState[] { + getFolderPaths(collapsed: boolean, currentFile: string): FolderState[] { const folderPaths: FolderState[] = [] const traverse = (node: FileNode, currentPath: string) => { diff --git a/quartz/components/scripts/explorer.inline.ts b/quartz/components/scripts/explorer.inline.ts index 33d328a6..ffe9ecbe 100644 --- a/quartz/components/scripts/explorer.inline.ts +++ b/quartz/components/scripts/explorer.inline.ts @@ -1,7 +1,13 @@ import { FolderState } from "../ExplorerNode" +// Current state of folders type MaybeHTMLElement = HTMLElement | undefined let currentExplorerState: FolderState[] + +function escapeCharacters(str: string) { + return str.replace(/'/g, "\\'").replace(/"/g, '\\"') +} + const observer = new IntersectionObserver((entries) => { // If last element is observed, remove gradient of "overflow" class so element is visible const explorerUl = document.getElementById("explorer-ul") @@ -15,24 +21,17 @@ const observer = new IntersectionObserver((entries) => { } }) -function toggleExplorer(this: HTMLElement) { - this.classList.toggle("collapsed") - this.setAttribute( - "aria-expanded", - this.getAttribute("aria-expanded") === "true" ? "false" : "true", - ) - const content = this.nextElementSibling as MaybeHTMLElement - if (!content) return - - content.classList.toggle("collapsed") -} - function toggleFolder(evt: MouseEvent) { evt.stopPropagation() + + // Element that was clicked const target = evt.target as MaybeHTMLElement if (!target) return + // Check if target was svg icon or button const isSvg = target.nodeName === "svg" + + // corresponding
    element relative to clicked button/folder const childFolderContainer = ( isSvg ? target.parentElement?.nextSibling @@ -42,68 +41,150 @@ function toggleFolder(evt: MouseEvent) { isSvg ? target.nextElementSibling : target.parentElement ) as MaybeHTMLElement if (!(childFolderContainer && currentFolderParent)) return - + //
  • element of folder (stores folder-path dataset) childFolderContainer.classList.toggle("open") + + // Collapse folder container const isCollapsed = childFolderContainer.classList.contains("open") setFolderState(childFolderContainer, !isCollapsed) + + // Save folder state to localStorage const fullFolderPath = currentFolderParent.dataset.folderpath as string toggleCollapsedByPath(currentExplorerState, fullFolderPath) const stringifiedFileTree = JSON.stringify(currentExplorerState) localStorage.setItem("fileTree", stringifiedFileTree) } +function toggleExplorer(this: HTMLElement) { + // Toggle collapsed state of entire explorer + this.classList.toggle("collapsed") + const content = this.nextElementSibling as MaybeHTMLElement + if (!content) return + content.classList.toggle("collapsed") + //content.style.maxHeight = content.style.maxHeight === "0px" ? content.scrollHeight + "px" : "0px" + content.style.maxHeight = content.style.maxHeight === "0px" ? "calc(100vh - 8rem)" : "0px" + + //prevent scroll under + if (this.dataset.mobile === "true" && document.querySelector("#mobile-explorer")) { + const article = document.querySelectorAll( + ".popover-hint, footer, .backlinks, .graph, .toc, #progress", + ) + const header = document.querySelector(".page .page-header") + if (article) + article.forEach((element) => { + element.classList.toggle("no-scroll") + }) + if (header) header.classList.toggle("fixed") + } +} + function setupExplorer() { - const explorer = document.getElementById("explorer") - if (!explorer) return + // Set click handler for collapsing entire explorer + const allExplorers = document.querySelectorAll(".explorer > button") as NodeListOf + + for (const explorer of allExplorers) { + // Get folder state from local storage + const storageTree = localStorage.getItem("fileTree") + + // Convert to bool + const useSavedFolderState = explorer?.dataset.savestate === "true" + + if (explorer) { + // Get config + const collapseBehavior = explorer.dataset.behavior + + // Add click handlers for all folders (click handler on folder "label") + if (collapseBehavior === "collapse") { + for (const item of document.getElementsByClassName( + "folder-button", + ) as HTMLCollectionOf) { + window.addCleanup(() => explorer.removeEventListener("click", toggleExplorer)) + item.addEventListener("click", toggleFolder) + } + } + + // Add click handler to main explorer + window.addCleanup(() => explorer.removeEventListener("click", toggleExplorer)) + explorer.addEventListener("click", toggleExplorer) + } - if (explorer.dataset.behavior === "collapse") { + // Set up click handlers for each folder (click handler on folder "icon") for (const item of document.getElementsByClassName( - "folder-button", + "folder-icon", ) as HTMLCollectionOf) { item.addEventListener("click", toggleFolder) window.addCleanup(() => item.removeEventListener("click", toggleFolder)) } - } - - explorer.addEventListener("click", toggleExplorer) - window.addCleanup(() => explorer.removeEventListener("click", toggleExplorer)) - // Set up click handlers for each folder (click handler on folder "icon") - for (const item of document.getElementsByClassName( - "folder-icon", - ) as HTMLCollectionOf) { - item.addEventListener("click", toggleFolder) - window.addCleanup(() => item.removeEventListener("click", toggleFolder)) - } + // Get folder state from local storage + const oldExplorerState: FolderState[] = + storageTree && useSavedFolderState ? JSON.parse(storageTree) : [] + const oldIndex = new Map(oldExplorerState.map((entry) => [entry.path, entry.collapsed])) + //console.log(explorer.dataset.tree) + //console.log(explorer.dataset.tree ? JSON.parse(explorer.dataset.tree) : []) + const newExplorerState: FolderState[] = explorer.dataset.tree + ? JSON.parse(explorer.dataset.tree) + : [] + currentExplorerState = [] + + for (const { path, collapsed } of newExplorerState) { + currentExplorerState.push({ path, collapsed: /*oldIndex.get(path) ?? */ collapsed }) + } - // Get folder state from local storage - const storageTree = localStorage.getItem("fileTree") - const useSavedFolderState = explorer?.dataset.savestate === "true" - const oldExplorerState: FolderState[] = - storageTree && useSavedFolderState ? JSON.parse(storageTree) : [] - const oldIndex = new Map(oldExplorerState.map((entry) => [entry.path, entry.collapsed])) - const newExplorerState: FolderState[] = explorer.dataset.tree - ? JSON.parse(explorer.dataset.tree) - : [] - currentExplorerState = [] - for (const { path, collapsed } of newExplorerState) { - currentExplorerState.push({ path, collapsed: oldIndex.get(path) ?? collapsed }) + currentExplorerState.map((folderState) => { + const folderLi = document.querySelector( + `[data-folderpath='${folderState.path.replace("'", "-")}']`, + ) as MaybeHTMLElement + const folderUl = folderLi?.parentElement?.nextElementSibling as MaybeHTMLElement + if (folderUl) { + setFolderState(folderUl, folderState.collapsed) + } + }) } +} - currentExplorerState.map((folderState) => { - const folderLi = document.querySelector( - `[data-folderpath='${folderState.path}']`, - ) as MaybeHTMLElement - const folderUl = folderLi?.parentElement?.nextElementSibling as MaybeHTMLElement - if (folderUl) { - setFolderState(folderUl, folderState.collapsed) +function toggleExplorerFolders() { + const currentFile = (document.querySelector("body")?.getAttribute("data-slug") ?? "").replace( + /\/index$/g, + "", + ) + const listToReplace = document.querySelectorAll(".folder-outer:has(> ul[data-folderul]") + + listToReplace.forEach((element) => { + if (element.children.length > 0) { + if (currentFile.includes(element.firstElementChild?.getAttribute("data-folderul") ?? "")) { + if (!element.classList.contains("open")) { + element.classList.add("open") + } + } } }) } window.addEventListener("resize", setupExplorer) + +document.addEventListener("DOMContentLoaded", () => { + const explorer = document.querySelector("#mobile-explorer") + if (explorer) { + explorer.classList.add("collapsed") + const content = explorer.nextElementSibling as HTMLElement + content.classList.add("collapsed") + content.style.maxHeight = "0px" + } + toggleExplorerFolders() +}) + document.addEventListener("nav", () => { + const explorer = document.querySelector("#mobile-explorer") + if (explorer) { + explorer.classList.add("collapsed") + const content = explorer.nextElementSibling as HTMLElement + content.classList.add("collapsed") + content.style.maxHeight = "0px" + } setupExplorer() + //add collapsed class to all folders + observer.disconnect() // select pseudo element at end of list @@ -111,6 +192,8 @@ document.addEventListener("nav", () => { if (lastItem) { observer.observe(lastItem) } + + toggleExplorerFolders() }) /** diff --git a/quartz/components/styles/explorer.scss b/quartz/components/styles/explorer.scss index 397fd024..01e526a0 100644 --- a/quartz/components/styles/explorer.scss +++ b/quartz/components/styles/explorer.scss @@ -1,15 +1,31 @@ @use "../../styles/variables.scss" as *; -.explorer { - display: flex; - flex-direction: column; - overflow-y: hidden; - &.desktop-only { - @media all and not ($mobile) { +.explorer-container { + .mobile-explorer { + display: none; + } + .desktop-explorer { + display: flex; + } + @media all and ($mobile) { + .mobile-explorer { display: flex; } + .desktop-explorer { + display: none; + } } - /*&:after { + + .mobile-explorer, + .desktop-explorer { + flex-direction: column; + overflow-y: hidden; + &.desktop-only { + @media all and not ($mobile) { + display: flex; + } + } + /*&:after { pointer-events: none; content: ""; width: 100%; @@ -21,161 +37,234 @@ transition: opacity 0.3s ease; background: linear-gradient(transparent 0px, var(--light)); }*/ -} - -button#explorer { - background-color: transparent; - border: none; - text-align: left; - cursor: pointer; - padding: 0; - color: var(--dark); - display: flex; - align-items: center; - - & h2 { - font-size: 1rem; - display: inline-block; - margin: 0; } - & .fold { - margin-left: 0.5rem; - transition: transform 0.3s ease; - opacity: 0.8; - } + button#mobile-explorer, + button#desktop-explorer { + background-color: transparent; + border: none; + text-align: left; + cursor: pointer; + padding: 0; + color: var(--dark); + display: flex; + align-items: center; - &.collapsed .fold { - transform: rotateZ(-90deg); - } -} + & h2 { + font-size: 1rem; + display: inline-block; + margin: 0; + } -.folder-outer { - display: grid; - grid-template-rows: 0fr; - transition: grid-template-rows 0.3s ease-in-out; -} + & .fold { + margin-left: 0.5rem; + transition: transform 0.3s ease; + opacity: 0.8; + } -.folder-outer.open { - grid-template-rows: 1fr; -} + &.collapsed .fold { + transform: rotateZ(-90deg); + } + } -.folder-outer > ul { - overflow: hidden; -} + .folder-outer { + display: grid; + grid-template-rows: 0fr; + transition: grid-template-rows 0.3s ease-in-out; + } -#explorer-content { - list-style: none; - overflow: hidden; - overflow-y: auto; - max-height: 100%; - transition: - max-height 0.35s ease, - visibility 0s linear 0s; - margin-top: 0.5rem; - visibility: visible; - - &.collapsed { - max-height: 0; - transition: - max-height 0.35s ease, - visibility 0s linear 0.35s; - visibility: hidden; + .folder-outer.open { + grid-template-rows: 1fr; } - & ul { + .folder-outer > ul { + overflow: hidden; + } + + #explorer-content { list-style: none; - margin: 0.08rem 0; - padding: 0; + overflow: hidden; + overflow-y: auto; + max-height: 100%; transition: max-height 0.35s ease, - transform 0.35s ease, - opacity 0.2s ease; - & li > a { - color: var(--dark); - opacity: 0.75; - pointer-events: all; - } - } - > #explorer-ul { - max-height: none; - } -} + visibility 0s linear 0s; + margin-top: 0.5rem; + visibility: visible; -svg { - pointer-events: all; + &.collapsed { + max-height: 0; + transition: + max-height 0.35s ease, + visibility 0s linear 0.35s; + visibility: hidden; + } - & > polyline { - pointer-events: none; + & ul { + list-style: none; + margin: 0.08rem 0; + padding: 0; + transition: + max-height 0.35s ease, + transform 0.35s ease, + opacity 0.2s ease; + & li > a { + color: var(--dark); + opacity: 0.75; + pointer-events: all; + } + } + > #explorer-ul { + max-height: none; + } } -} - -.folder-container { - flex-direction: row; - display: flex; - align-items: center; - user-select: none; - & div > a { - color: var(--secondary); - font-family: var(--headerFont); - font-size: 0.95rem; - font-weight: $semiBoldWeight; - line-height: 1.5rem; - display: inline-block; - } + svg { + pointer-events: all; - & div > a:hover { - color: var(--tertiary); + & > polyline { + pointer-events: none; + } } - & div > button { - color: var(--dark); - background-color: transparent; - border: none; - text-align: left; - cursor: pointer; - padding-left: 0; - padding-right: 0; + .folder-container { + flex-direction: row; display: flex; align-items: center; - font-family: var(--headerFont); + user-select: none; - & span { - font-size: 0.95rem; - display: inline-block; + & div > a { color: var(--secondary); + font-family: var(--headerFont); + font-size: 0.95rem; font-weight: $semiBoldWeight; - margin: 0; line-height: 1.5rem; - pointer-events: none; + display: inline-block; + } + + & div > a:hover { + color: var(--tertiary); + } + + & div > button { + color: var(--dark); + background-color: transparent; + border: none; + text-align: left; + cursor: pointer; + padding-left: 0; + padding-right: 0; + display: flex; + align-items: center; + font-family: var(--headerFont); + + & span { + font-size: 0.95rem; + display: inline-block; + color: var(--secondary); + font-weight: $semiBoldWeight; + margin: 0; + line-height: 1.5rem; + pointer-events: none; + } } } -} -.folder-icon { - margin-right: 5px; - color: var(--secondary); - cursor: pointer; - transition: transform 0.3s ease; - backface-visibility: visible; -} + .folder-icon { + margin-right: 5px; + color: var(--secondary); + cursor: pointer; + transition: transform 0.3s ease; + backface-visibility: visible; + } -li:has(> .folder-outer:not(.open)) > .folder-container > svg { - transform: rotate(-90deg); -} + li:has(> .folder-outer:not(.open)) > .folder-container > svg { + transform: rotate(-90deg); + } -.folder-icon:hover { - color: var(--tertiary); -} + .folder-icon:hover { + color: var(--tertiary); + } -.no-background::after { - background: none !important; -} + .no-background::after { + background: none !important; + } + + #explorer-end { + // needs height so IntersectionObserver gets triggered + height: 4px; + // remove default margin from li + margin: 0; + } + + .mobile-explorer, + .desktop-explorer { + #explorer-content { + //left: 0; + z-index: 100; + position: absolute; + //max-height: max-content !important; + background-color: var(--light); + //max-width: calc(100% - 36px); + max-width: 100%; + width: calc(100% - 36px + 4px); + //margin-right: 36px; + transition: all 300ms ease-in-out; + overflow: hidden; + padding: 0 16px; + height: calc(100dvh - 8rem); + //border-top-left-radius: 23px; + //border-top-right-radius: 23px; + border-radius: 23px; + margin-top: 36px; + + &:not(.collapsed) { + height: calc(100dvh - 8rem); + //top: 10dvh; + } + + ul.overflow { + max-height: calc(100dvh - 8rem); + width: 100%; + } -#explorer-end { - // needs height so IntersectionObserver gets triggered - height: 4px; - // remove default margin from li - margin: 0; + &.collapsed { + height: 0; + } + } + + #mobile-explorer, + #desktop-explorer { + &:not(.collapsed) .lucide-menu { + transform: rotate(90deg); + transition: transform 200ms ease-in-out; + } + .lucide-menu { + stroke: var(--darkgray); + transition: transform 200ms ease; + &:hover { + stroke: var(--dark); + } + } + } + } + + .no-scroll { + opacity: 0; + overflow: hidden; + } + + html:has(.no-scroll) { + overflow: hidden; + } + + @media all and not ($mobile) { + .no-scroll { + opacity: 1 !important; + overflow: auto !important; + } + html:has(.no-scroll) { + overflow: auto !important; + } + } } From 139573ffd6e036777ab0727cb43545aa23e783ad Mon Sep 17 00:00:00 2001 From: saberzero1 Date: Tue, 1 Oct 2024 23:24:08 +0200 Subject: [PATCH 02/23] Finished mobile explorer --- quartz/components/scripts/explorer.inline.ts | 8 ++--- quartz/components/styles/explorer.scss | 33 +++++++++++++------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/quartz/components/scripts/explorer.inline.ts b/quartz/components/scripts/explorer.inline.ts index ffe9ecbe..49b9fdf0 100644 --- a/quartz/components/scripts/explorer.inline.ts +++ b/quartz/components/scripts/explorer.inline.ts @@ -62,19 +62,19 @@ function toggleExplorer(this: HTMLElement) { if (!content) return content.classList.toggle("collapsed") //content.style.maxHeight = content.style.maxHeight === "0px" ? content.scrollHeight + "px" : "0px" - content.style.maxHeight = content.style.maxHeight === "0px" ? "calc(100vh - 8rem)" : "0px" + content.style.maxHeight = content.style.maxHeight === "0px" ? "100vh" : "0px" //prevent scroll under - if (this.dataset.mobile === "true" && document.querySelector("#mobile-explorer")) { + if (document.querySelector("#mobile-explorer")) { const article = document.querySelectorAll( ".popover-hint, footer, .backlinks, .graph, .toc, #progress", ) - const header = document.querySelector(".page .page-header") + const header = document.querySelector("#quartz-body") if (article) article.forEach((element) => { element.classList.toggle("no-scroll") }) - if (header) header.classList.toggle("fixed") + if (header) header.classList.toggle("lock-scroll") } } diff --git a/quartz/components/styles/explorer.scss b/quartz/components/styles/explorer.scss index 01e526a0..9f508fd2 100644 --- a/quartz/components/styles/explorer.scss +++ b/quartz/components/styles/explorer.scss @@ -1,6 +1,7 @@ @use "../../styles/variables.scss" as *; .explorer-container { + overflow-y: hidden; .mobile-explorer { display: none; } @@ -18,6 +19,7 @@ .mobile-explorer, .desktop-explorer { + height: 100%; flex-direction: column; overflow-y: hidden; &.desktop-only { @@ -197,25 +199,25 @@ margin: 0; } - .mobile-explorer, - .desktop-explorer { + .mobile-explorer { #explorer-content { + overscroll-behavior: none; //left: 0; z-index: 100; position: absolute; //max-height: max-content !important; background-color: var(--light); - //max-width: calc(100% - 36px); - max-width: 100%; - width: calc(100% - 36px + 4px); - //margin-right: 36px; + max-width: calc(100% - 4rem); + left: 0; + width: 100%; transition: all 300ms ease-in-out; overflow: hidden; - padding: 0 16px; - height: calc(100dvh - 8rem); + padding: 1rem 2rem 5rem; + //height: calc(100dvh - 36px); + height: 100%; + max-height: calc(100dvh - 8rem); //border-top-left-radius: 23px; //border-top-right-radius: 23px; - border-radius: 23px; margin-top: 36px; &:not(.collapsed) { @@ -233,8 +235,7 @@ } } - #mobile-explorer, - #desktop-explorer { + #mobile-explorer { &:not(.collapsed) .lucide-menu { transform: rotate(90deg); transition: transform 200ms ease-in-out; @@ -268,3 +269,13 @@ } } } + +// Lock page scroll on mobile +.lock-scroll { + position: static; +} +@media all and ($mobile) { + .lock-scroll { + position: fixed; + } +} From 836f2a87ad1162aaf14d845b1ab34025e6a21bce Mon Sep 17 00:00:00 2001 From: saberzero1 Date: Tue, 1 Oct 2024 23:46:40 +0200 Subject: [PATCH 03/23] Fix folder/tag page --- quartz.layout.ts | 2 +- quartz/components/scripts/explorer.inline.ts | 2 +- quartz/components/styles/explorer.scss | 3 +++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/quartz.layout.ts b/quartz.layout.ts index ab4c0c84..f45da0c9 100644 --- a/quartz.layout.ts +++ b/quartz.layout.ts @@ -44,7 +44,7 @@ export const defaultListPageLayout: PageLayout = { Component.MobileOnly(Component.Spacer()), Component.Search(), Component.Darkmode(), - Component.DesktopOnly(Component.Explorer()), + Component.Explorer(), ], right: [], } diff --git a/quartz/components/scripts/explorer.inline.ts b/quartz/components/scripts/explorer.inline.ts index 49b9fdf0..139549da 100644 --- a/quartz/components/scripts/explorer.inline.ts +++ b/quartz/components/scripts/explorer.inline.ts @@ -62,7 +62,7 @@ function toggleExplorer(this: HTMLElement) { if (!content) return content.classList.toggle("collapsed") //content.style.maxHeight = content.style.maxHeight === "0px" ? content.scrollHeight + "px" : "0px" - content.style.maxHeight = content.style.maxHeight === "0px" ? "100vh" : "0px" + content.style.maxHeight = content.style.maxHeight === "0px" ? "100dvh" : "0px" //prevent scroll under if (document.querySelector("#mobile-explorer")) { diff --git a/quartz/components/styles/explorer.scss b/quartz/components/styles/explorer.scss index 9f508fd2..421ddb4b 100644 --- a/quartz/components/styles/explorer.scss +++ b/quartz/components/styles/explorer.scss @@ -9,6 +9,7 @@ display: flex; } @media all and ($mobile) { + order: -1; .mobile-explorer { display: flex; } @@ -236,6 +237,7 @@ } #mobile-explorer { + margin: 5px; &:not(.collapsed) .lucide-menu { transform: rotate(90deg); transition: transform 200ms ease-in-out; @@ -277,5 +279,6 @@ @media all and ($mobile) { .lock-scroll { position: fixed; + width: calc(100% - 2rem); } } From 526e50aff08c8cab251455ce9439976c7077421a Mon Sep 17 00:00:00 2001 From: saberzero1 Date: Tue, 1 Oct 2024 23:49:23 +0200 Subject: [PATCH 04/23] Cleanup --- quartz/components/styles/explorer.scss | 6 ------ 1 file changed, 6 deletions(-) diff --git a/quartz/components/styles/explorer.scss b/quartz/components/styles/explorer.scss index 421ddb4b..fc00794f 100644 --- a/quartz/components/styles/explorer.scss +++ b/quartz/components/styles/explorer.scss @@ -203,10 +203,8 @@ .mobile-explorer { #explorer-content { overscroll-behavior: none; - //left: 0; z-index: 100; position: absolute; - //max-height: max-content !important; background-color: var(--light); max-width: calc(100% - 4rem); left: 0; @@ -214,16 +212,12 @@ transition: all 300ms ease-in-out; overflow: hidden; padding: 1rem 2rem 5rem; - //height: calc(100dvh - 36px); height: 100%; max-height: calc(100dvh - 8rem); - //border-top-left-radius: 23px; - //border-top-right-radius: 23px; margin-top: 36px; &:not(.collapsed) { height: calc(100dvh - 8rem); - //top: 10dvh; } ul.overflow { From 7d404acedd457702a5367d5ee1d734cf185e9a00 Mon Sep 17 00:00:00 2001 From: saberzero1 Date: Wed, 2 Oct 2024 00:53:24 +0200 Subject: [PATCH 05/23] Combine into single explorer tree --- quartz/components/Explorer.tsx | 10 +- quartz/components/scripts/explorer.inline.ts | 16 ++- quartz/components/styles/explorer.scss | 118 ++++++++++--------- 3 files changed, 72 insertions(+), 72 deletions(-) diff --git a/quartz/components/Explorer.tsx b/quartz/components/Explorer.tsx index ea43815e..a40620a1 100644 --- a/quartz/components/Explorer.tsx +++ b/quartz/components/Explorer.tsx @@ -88,7 +88,7 @@ export default ((userOpts?: Partial) => { } return (
    -
    +
    - -
    -
    -
    +
    • diff --git a/quartz/components/ExplorerNode.tsx b/quartz/components/ExplorerNode.tsx index 88246e04..9b3080fc 100644 --- a/quartz/components/ExplorerNode.tsx +++ b/quartz/components/ExplorerNode.tsx @@ -134,8 +134,11 @@ export class FileNode { const traverse = (node: FileNode, currentPath: string) => { if (!node.file) { const folderPath = joinSegments(currentPath, node.name) + const collapseState = !currentFile.includes( + folderPath.replace("'", "-").replaceAll("../", ""), + ) if (folderPath !== "") { - folderPaths.push({ path: folderPath, collapsed }) + folderPaths.push({ path: folderPath, collapsed: collapseState || collapsed }) } node.children.forEach((child) => traverse(child, folderPath)) From 40ca67c8c6f46600bb571ba942b2689bd44b02cd Mon Sep 17 00:00:00 2001 From: saberzero1 Date: Thu, 3 Oct 2024 22:13:46 +0200 Subject: [PATCH 14/23] Remove usePagePath --- quartz/components/Explorer.tsx | 6 +----- quartz/components/ExplorerNode.tsx | 9 ++------- quartz/components/scripts/explorer.inline.ts | 3 +-- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/quartz/components/Explorer.tsx b/quartz/components/Explorer.tsx index d5c34dd2..4c8eba65 100644 --- a/quartz/components/Explorer.tsx +++ b/quartz/components/Explorer.tsx @@ -13,7 +13,6 @@ const defaultOptions = { folderClickBehavior: "collapse", folderDefaultState: "collapsed", useSavedState: true, - usePagePath: false, mapFn: (node) => { return node }, @@ -70,8 +69,7 @@ export default ((userOpts?: Partial) => { // Get all folders of tree. Initialize with collapsed state // Stringify to pass json tree as data attribute ([data-tree]) const folders = fileTree.getFolderPaths( - opts.folderDefaultState === "collapsed", - currentFilePath, + opts.folderDefaultState === "collapsed" ) jsonTree = JSON.stringify(folders) } @@ -97,7 +95,6 @@ export default ((userOpts?: Partial) => { data-behavior={opts.folderClickBehavior} data-collapsed={opts.folderDefaultState} data-savestate={opts.useSavedState} - data-pagepathstate={opts.usePagePath} data-tree={jsonTree} data-mobile={true} aria-controls="explorer-content" @@ -125,7 +122,6 @@ export default ((userOpts?: Partial) => { data-behavior={opts.folderClickBehavior} data-collapsed={opts.folderDefaultState} data-savestate={opts.useSavedState} - data-pagepathstate={opts.usePagePath} data-tree={jsonTree} data-mobile={false} aria-controls="explorer-content" diff --git a/quartz/components/ExplorerNode.tsx b/quartz/components/ExplorerNode.tsx index 9b3080fc..e57d6771 100644 --- a/quartz/components/ExplorerNode.tsx +++ b/quartz/components/ExplorerNode.tsx @@ -16,7 +16,6 @@ export interface Options { folderDefaultState: "collapsed" | "open" folderClickBehavior: "collapse" | "link" useSavedState: boolean - usePagePath: boolean sortFn: (a: FileNode, b: FileNode) => number filterFn: (node: FileNode) => boolean mapFn: (node: FileNode) => void @@ -125,20 +124,16 @@ export class FileNode { * Get folder representation with state of tree. * Intended to only be called on root node before changes to the tree are made * @param collapsed default state of folders (collapsed by default or not) - * @param currentFile current file * @returns array containing folder state for tree */ - getFolderPaths(collapsed: boolean, currentFile: string): FolderState[] { + getFolderPaths(collapsed: boolean): FolderState[] { const folderPaths: FolderState[] = [] const traverse = (node: FileNode, currentPath: string) => { if (!node.file) { const folderPath = joinSegments(currentPath, node.name) - const collapseState = !currentFile.includes( - folderPath.replace("'", "-").replaceAll("../", ""), - ) if (folderPath !== "") { - folderPaths.push({ path: folderPath, collapsed: collapseState || collapsed }) + folderPaths.push({ path: folderPath, collapsed }) } node.children.forEach((child) => traverse(child, folderPath)) diff --git a/quartz/components/scripts/explorer.inline.ts b/quartz/components/scripts/explorer.inline.ts index 11703b33..a59224d0 100644 --- a/quartz/components/scripts/explorer.inline.ts +++ b/quartz/components/scripts/explorer.inline.ts @@ -88,7 +88,6 @@ function setupExplorer() { // Convert to bool const useSavedFolderState = explorer?.dataset.savestate === "true" - const usePagePathState = explorer?.dataset.pagepathstate === "true" if (explorer) { // Get config @@ -129,7 +128,7 @@ function setupExplorer() { for (const { path, collapsed } of newExplorerState) { currentExplorerState.push({ path, - collapsed: usePagePathState ? (oldIndex.get(path) ?? collapsed) : collapsed, + collapsed: oldIndex.get(path) ?? collapsed, }) } From ff9be50a5635f45d5f9275b9fb55b325c361d4a8 Mon Sep 17 00:00:00 2001 From: saberzero1 Date: Thu, 3 Oct 2024 22:17:25 +0200 Subject: [PATCH 15/23] Prettier --- quartz/components/Explorer.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/quartz/components/Explorer.tsx b/quartz/components/Explorer.tsx index 4c8eba65..d4b48815 100644 --- a/quartz/components/Explorer.tsx +++ b/quartz/components/Explorer.tsx @@ -68,9 +68,7 @@ export default ((userOpts?: Partial) => { // Get all folders of tree. Initialize with collapsed state // Stringify to pass json tree as data attribute ([data-tree]) - const folders = fileTree.getFolderPaths( - opts.folderDefaultState === "collapsed" - ) + const folders = fileTree.getFolderPaths(opts.folderDefaultState === "collapsed") jsonTree = JSON.stringify(folders) } From fda7b66e64c845eeb4920f9169c8d7684ae878b1 Mon Sep 17 00:00:00 2001 From: Emile Bangma Date: Sat, 5 Oct 2024 00:59:11 +0200 Subject: [PATCH 16/23] Update quartz/components/Footer.tsx Co-authored-by: Aaron Pham --- quartz/components/Footer.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/quartz/components/Footer.tsx b/quartz/components/Footer.tsx index fb121a38..cff28cbb 100644 --- a/quartz/components/Footer.tsx +++ b/quartz/components/Footer.tsx @@ -1,7 +1,6 @@ import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types" import style from "./styles/footer.scss" import { version } from "../../package.json" -import { classNames } from "../util/lang" import { i18n } from "../i18n" interface Options { From 316a993fed7b39fc2b1c4461f56a0b7234e0e098 Mon Sep 17 00:00:00 2001 From: saberzero1 Date: Fri, 25 Oct 2024 18:45:47 +0200 Subject: [PATCH 17/23] Changed mobile explorer from dropdown to slide-in --- quartz/components/styles/explorer.scss | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/quartz/components/styles/explorer.scss b/quartz/components/styles/explorer.scss index 156613df..769cb06c 100644 --- a/quartz/components/styles/explorer.scss +++ b/quartz/components/styles/explorer.scss @@ -205,33 +205,36 @@ .explorer { @media all and ($mobile) { #explorer-content { + box-sizing: border-box; overscroll-behavior: none; z-index: 100; position: absolute; background-color: var(--light); - max-width: calc(100% - 4rem); - left: 0; - width: 100%; + max-width: 100dvw; + left: -100dvw; + width: 100dvw; transition: all 300ms ease-in-out; overflow: hidden; padding: 2rem 2rem 4rem; - height: 100%; - max-height: calc(100dvh - 8rem); + height: calc(100dvh - 4rem); + max-height: calc(100dvh - 4rem); margin-top: 2rem; visibility: visible; &:not(.collapsed) { - height: calc(100dvh - 8rem); + //height: 100dvh; + left: 0; } ul.overflow { - max-height: calc(100dvh - 8rem); + max-height: 100%; width: 100%; } &.collapsed { - height: 0; - visibility: hidden; + //height: 0; + left: -100dvw; + visibility: visible; } } From 979d653b1a5bd0435815938434b5590a0671592a Mon Sep 17 00:00:00 2001 From: saberzero1 Date: Sat, 26 Oct 2024 12:26:43 +0200 Subject: [PATCH 18/23] Remove container div --- quartz/components/Explorer.tsx | 120 ++++--- quartz/components/styles/explorer.scss | 429 +++++++++++++------------ 2 files changed, 279 insertions(+), 270 deletions(-) diff --git a/quartz/components/Explorer.tsx b/quartz/components/Explorer.tsx index d4b48815..e598d12d 100644 --- a/quartz/components/Explorer.tsx +++ b/quartz/components/Explorer.tsx @@ -84,69 +84,67 @@ export default ((userOpts?: Partial) => { constructFileTree(allFiles, (fileData.filePath ?? "").replaceAll(" ", "-")) } return ( -
      -
      - - + -
      -
        - -
      • -
      -
      + + + +
      +
        + +
      • +
      ) diff --git a/quartz/components/styles/explorer.scss b/quartz/components/styles/explorer.scss index 769cb06c..322818af 100644 --- a/quartz/components/styles/explorer.scss +++ b/quartz/components/styles/explorer.scss @@ -1,277 +1,287 @@ @use "../../styles/variables.scss" as *; -.explorer-container { - overflow-y: hidden; +.explorer { @media all and ($mobile) { order: -1; + height: initial; + overflow: hidden; + } + + display: flex; + + button#mobile-explorer { + display: none; } - .explorer { + button#desktop-explorer { display: flex; + } + + @media all and ($mobile) { button#mobile-explorer { - display: none; - } - button#desktop-explorer { display: flex; } - @media all and ($mobile) { - button#mobile-explorer { - display: flex; - } - button#desktop-explorer { - display: none; - } - } - height: 100%; - flex-direction: column; - overflow-y: hidden; - &.desktop-only { - @media all and not ($mobile) { - display: flex; - } + + button#desktop-explorer { + display: none; } - /*&:after { - pointer-events: none; - content: ""; - width: 100%; - height: 50px; - position: absolute; - left: 0; - bottom: 0; - opacity: 1; - transition: opacity 0.3s ease; - background: linear-gradient(transparent 0px, var(--light)); - }*/ } - button#mobile-explorer, - button#desktop-explorer { - background-color: transparent; - border: none; - text-align: left; - cursor: pointer; - padding: 0; - color: var(--dark); - display: flex; - align-items: center; + height: 100%; + flex-direction: column; + overflow-y: hidden; - & h2 { - font-size: 1rem; - display: inline-block; - margin: 0; + &.desktop-only { + @media all and not ($mobile) { + display: flex; } + } - & .fold { - margin-left: 0.5rem; - transition: transform 0.3s ease; - opacity: 0.8; - } + /*&:after { + pointer-events: none; + content: ""; + width: 100%; + height: 50px; + position: absolute; + left: 0; + bottom: 0; + opacity: 1; + transition: opacity 0.3s ease; + background: linear-gradient(transparent 0px, var(--light)); +}*/ +} - &.collapsed .fold { - transform: rotateZ(-90deg); - } +button#mobile-explorer, +button#desktop-explorer { + background-color: transparent; + border: none; + text-align: left; + cursor: pointer; + padding: 0; + color: var(--dark); + display: flex; + align-items: center; + + & h2 { + font-size: 1rem; + display: inline-block; + margin: 0; } - .folder-outer { - display: grid; - grid-template-rows: 0fr; - transition: grid-template-rows 0.3s ease-in-out; + & .fold { + margin-left: 0.5rem; + transition: transform 0.3s ease; + opacity: 0.8; } - .folder-outer.open { - grid-template-rows: 1fr; + &.collapsed .fold { + transform: rotateZ(-90deg); } +} - .folder-outer > ul { - overflow: hidden; +.folder-outer { + display: grid; + grid-template-rows: 0fr; + transition: grid-template-rows 0.3s ease-in-out; +} + +.folder-outer.open { + grid-template-rows: 1fr; +} + +.folder-outer > ul { + overflow: hidden; +} + +#explorer-content { + list-style: none; + overflow: hidden; + overflow-y: auto; + max-height: 0px; + transition: + max-height 0.35s ease, + visibility 0s linear 0.35s; + margin-top: 0.5rem; + visibility: hidden; + + &.collapsed { + max-height: 100%; + transition: + max-height 0.35s ease, + visibility 0s linear 0s; + visibility: visible; } - #explorer-content { + & ul { list-style: none; - overflow: hidden; - overflow-y: auto; - max-height: 0px; + margin: 0.08rem 0; + padding: 0; transition: max-height 0.35s ease, - visibility 0s linear 0.35s; - margin-top: 0.5rem; - visibility: hidden; - - &.collapsed { - max-height: 100%; - transition: - max-height 0.35s ease, - visibility 0s linear 0s; - visibility: visible; - } + transform 0.35s ease, + opacity 0.2s ease; - & ul { - list-style: none; - margin: 0.08rem 0; - padding: 0; - transition: - max-height 0.35s ease, - transform 0.35s ease, - opacity 0.2s ease; - & li > a { - color: var(--dark); - opacity: 0.75; - pointer-events: all; - } - } - > #explorer-ul { - max-height: none; + & li > a { + color: var(--dark); + opacity: 0.75; + pointer-events: all; } } - svg { - pointer-events: all; + > #explorer-ul { + max-height: none; + } +} + +svg { + pointer-events: all; - & > polyline { - pointer-events: none; - } + & > polyline { + pointer-events: none; } +} - .folder-container { - flex-direction: row; +.folder-container { + flex-direction: row; + display: flex; + align-items: center; + user-select: none; + + & div > a { + color: var(--secondary); + font-family: var(--headerFont); + font-size: 0.95rem; + font-weight: $semiBoldWeight; + line-height: 1.5rem; + display: inline-block; + } + + & div > a:hover { + color: var(--tertiary); + } + + & div > button { + color: var(--dark); + background-color: transparent; + border: none; + text-align: left; + cursor: pointer; + padding-left: 0; + padding-right: 0; display: flex; align-items: center; - user-select: none; + font-family: var(--headerFont); - & div > a { - color: var(--secondary); - font-family: var(--headerFont); + & span { font-size: 0.95rem; + display: inline-block; + color: var(--secondary); font-weight: $semiBoldWeight; + margin: 0; line-height: 1.5rem; - display: inline-block; + pointer-events: none; } + } +} - & div > a:hover { - color: var(--tertiary); - } +.folder-icon { + margin-right: 5px; + color: var(--secondary); + cursor: pointer; + transition: transform 0.3s ease; + backface-visibility: visible; +} - & div > button { - color: var(--dark); - background-color: transparent; - border: none; - text-align: left; - cursor: pointer; - padding-left: 0; - padding-right: 0; - display: flex; - align-items: center; - font-family: var(--headerFont); - - & span { - font-size: 0.95rem; - display: inline-block; - color: var(--secondary); - font-weight: $semiBoldWeight; - margin: 0; - line-height: 1.5rem; - pointer-events: none; - } - } - } +li:has(> .folder-outer:not(.open)) > .folder-container > svg { + transform: rotate(-90deg); +} - .folder-icon { - margin-right: 5px; - color: var(--secondary); - cursor: pointer; - transition: transform 0.3s ease; - backface-visibility: visible; - } +.folder-icon:hover { + color: var(--tertiary); +} - li:has(> .folder-outer:not(.open)) > .folder-container > svg { - transform: rotate(-90deg); - } +.no-background::after { + background: none !important; +} - .folder-icon:hover { - color: var(--tertiary); - } +#explorer-end { + // needs height so IntersectionObserver gets triggered + height: 4px; + // remove default margin from li + margin: 0; +} - .no-background::after { - background: none !important; - } +.explorer { + @media all and ($mobile) { + #explorer-content { + box-sizing: border-box; + overscroll-behavior: none; + z-index: 100; + position: absolute; + background-color: var(--light); + max-width: 100dvw; + left: -100dvw; + width: 100%; + transition: all 300ms ease-in-out; + overflow: hidden; + padding: 2rem 2rem 4rem; + height: calc(100dvh - 4rem); + max-height: calc(100dvh - 4rem); + margin-top: 2rem; + visibility: visible; - #explorer-end { - // needs height so IntersectionObserver gets triggered - height: 4px; - // remove default margin from li - margin: 0; - } + &:not(.collapsed) { + left: 0; + } + + ul.overflow { + max-height: 100%; + width: 100%; + } - .explorer { - @media all and ($mobile) { - #explorer-content { - box-sizing: border-box; - overscroll-behavior: none; - z-index: 100; - position: absolute; - background-color: var(--light); - max-width: 100dvw; + &.collapsed { left: -100dvw; - width: 100dvw; - transition: all 300ms ease-in-out; - overflow: hidden; - padding: 2rem 2rem 4rem; - height: calc(100dvh - 4rem); - max-height: calc(100dvh - 4rem); - margin-top: 2rem; visibility: visible; + } + } - &:not(.collapsed) { - //height: 100dvh; - left: 0; - } - - ul.overflow { - max-height: 100%; - width: 100%; - } + #mobile-explorer { + margin: 5px; - &.collapsed { - //height: 0; - left: -100dvw; - visibility: visible; - } + &:not(.collapsed) .lucide-menu { + transform: rotate(-90deg); + transition: transform 200ms ease-in-out; } - #mobile-explorer { - margin: 5px; - &:not(.collapsed) .lucide-menu { - transform: rotate(90deg); - transition: transform 200ms ease-in-out; - } - .lucide-menu { - stroke: var(--darkgray); - transition: transform 200ms ease; - &:hover { - stroke: var(--dark); - } + .lucide-menu { + stroke: var(--darkgray); + transition: transform 200ms ease; + + &:hover { + stroke: var(--dark); } } } } +} + +.no-scroll { + opacity: 0; + overflow: hidden; +} + +html:has(.no-scroll) { + overflow: hidden; +} +@media all and not ($mobile) { .no-scroll { - opacity: 0; - overflow: hidden; + opacity: 1 !important; + overflow: auto !important; } html:has(.no-scroll) { - overflow: hidden; - } - - @media all and not ($mobile) { - .no-scroll { - opacity: 1 !important; - overflow: auto !important; - } - html:has(.no-scroll) { - overflow: auto !important; - } + overflow: auto !important; } } @@ -279,6 +289,7 @@ .lock-scroll { position: static; } + @media all and ($mobile) { .lock-scroll { position: fixed; From 90e984e98b21a601c2461f285d35fe73509ee7af Mon Sep 17 00:00:00 2001 From: saberzero1 Date: Sat, 26 Oct 2024 14:44:58 +0200 Subject: [PATCH 19/23] Restore position --- quartz/components/scripts/explorer.inline.ts | 13 +++++++- quartz/components/styles/explorer.scss | 32 +++++++++----------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/quartz/components/scripts/explorer.inline.ts b/quartz/components/scripts/explorer.inline.ts index a59224d0..1d8bf854 100644 --- a/quartz/components/scripts/explorer.inline.ts +++ b/quartz/components/scripts/explorer.inline.ts @@ -40,7 +40,18 @@ function toggleExplorer(this: HTMLElement) { if (document.querySelector("#mobile-explorer")) { // Disable scrolling one the page when the explorer is opened on mobile const bodySelector = document.querySelector("#quartz-body") - if (bodySelector) bodySelector.classList.toggle("lock-scroll") + if (bodySelector) { + if (!bodySelector.classList.contains("lock-scroll")) { + bodySelector.setAttribute("scroll-position", `${window.scrollY}`) + bodySelector.classList.toggle("lock-scroll") + } else { + bodySelector.classList.toggle("lock-scroll") + window.scrollTo({ + top: Number(bodySelector.getAttribute("scroll-position")), + behavior: "instant", + }) + } + } } } diff --git a/quartz/components/styles/explorer.scss b/quartz/components/styles/explorer.scss index 322818af..0c221ca6 100644 --- a/quartz/components/styles/explorer.scss +++ b/quartz/components/styles/explorer.scss @@ -1,14 +1,23 @@ @use "../../styles/variables.scss" as *; +// Sticky top bar (stays in place when scrolling down on mobile. +@media all and ($mobile) { + .page > #quartz-body .sidebar.left:has(.explorer) { + box-sizing: border-box; + position: sticky; + background-color: var(--light); + } +} + .explorer { + display: flex; + @media all and ($mobile) { order: -1; height: initial; overflow: hidden; } - display: flex; - button#mobile-explorer { display: none; } @@ -220,7 +229,8 @@ li:has(> .folder-outer:not(.open)) > .folder-container > svg { position: absolute; background-color: var(--light); max-width: 100dvw; - left: -100dvw; + //left: -100dvw; + transform: translateX(-100dvw); width: 100%; transition: all 300ms ease-in-out; overflow: hidden; @@ -231,7 +241,7 @@ li:has(> .folder-outer:not(.open)) > .folder-container > svg { visibility: visible; &:not(.collapsed) { - left: 0; + transform: translateX(0); } ul.overflow { @@ -240,7 +250,7 @@ li:has(> .folder-outer:not(.open)) > .folder-container > svg { } &.collapsed { - left: -100dvw; + transform: translateX(-100dvw); visibility: visible; } } @@ -284,15 +294,3 @@ html:has(.no-scroll) { overflow: auto !important; } } - -// Lock page scroll on mobile -.lock-scroll { - position: static; -} - -@media all and ($mobile) { - .lock-scroll { - position: fixed; - width: calc(100% - 2rem); - } -} From c2e94779413b4d12aeaac0089efecc941355ccb5 Mon Sep 17 00:00:00 2001 From: saberzero1 Date: Sat, 26 Oct 2024 18:01:02 +0200 Subject: [PATCH 20/23] Slide in + no ugly onload animation on mobile --- quartz/components/Explorer.tsx | 2 +- quartz/components/scripts/explorer.inline.ts | 17 +++----- quartz/components/styles/explorer.scss | 43 ++++++++++++++------ 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/quartz/components/Explorer.tsx b/quartz/components/Explorer.tsx index e598d12d..1f2f3e0f 100644 --- a/quartz/components/Explorer.tsx +++ b/quartz/components/Explorer.tsx @@ -88,7 +88,7 @@ export default ((userOpts?: Partial) => {