From bb24cd13c7fafbd42d3980c45351a58a76dabb18 Mon Sep 17 00:00:00 2001 From: 1 gal Rosemary Date: Sun, 6 Apr 2025 01:39:28 +0800 Subject: [PATCH] fix(css): styles issues with popover, overflow, and scroll overflow (#1907) * fix(style): fix toc overflow & scrolling overflow * fix(style): fix explorer scrolling overflow * fix(style): fix backlinks overflow & scrolling overflow * fix(style): resolve popover overflow issue causing incomplete display * chore: rename function to enhance readability * fix(popover): make the backlink's id unique & use translate() instead of translateY() --- quartz/components/scripts/popover.inline.ts | 36 +++++++++++++++++---- quartz/components/styles/backlinks.scss | 2 ++ quartz/components/styles/explorer.scss | 1 + quartz/components/styles/popover.scss | 8 +++-- quartz/components/styles/toc.scss | 2 ++ 5 files changed, 40 insertions(+), 9 deletions(-) diff --git a/quartz/components/scripts/popover.inline.ts b/quartz/components/scripts/popover.inline.ts index 7d8aec352..d02b0b725 100644 --- a/quartz/components/scripts/popover.inline.ts +++ b/quartz/components/scripts/popover.inline.ts @@ -1,33 +1,40 @@ import { computePosition, flip, inline, shift } from "@floating-ui/dom" import { normalizeRelativeURLs } from "../../util/path" import { fetchCanonical } from "./util" +import { randomIdNonSecure } from "../../util/random" const p = new DOMParser() + async function mouseEnterHandler( this: HTMLAnchorElement, { clientX, clientY }: { clientX: number; clientY: number }, ) { + clearActivePopover() + const link = this + link.id = `backlink-${randomIdNonSecure()}` if (link.dataset.noPopover === "true") { return } async function setPosition(popoverElement: HTMLElement) { const { x, y } = await computePosition(link, popoverElement, { + strategy: "fixed", middleware: [inline({ x: clientX, y: clientY }), shift(), flip()], }) Object.assign(popoverElement.style, { - left: `${x}px`, - top: `${y}px`, + transform: `translate(${x}px, ${y}px)`, }) } - const hasAlreadyBeenFetched = () => - [...link.children].some((child) => child.classList.contains("popover")) + const prevPopoverElement = document.getElementById(`popover-${link.id.split("-")[1]}`) + const hasAlreadyBeenFetched = () => !!prevPopoverElement // dont refetch if there's already a popover if (hasAlreadyBeenFetched()) { - return setPosition(link.lastChild as HTMLElement) + setPosition(prevPopoverElement as HTMLElement) + prevPopoverElement?.classList.add("active-popover") + return } const thisUrl = new URL(document.location.href) @@ -94,7 +101,9 @@ async function mouseEnterHandler( } setPosition(popoverElement) - link.appendChild(popoverElement) + popoverElement.id = `popover-${link.id.split("-")[1]}` + popoverElement?.classList.add("active-popover") + document.body.appendChild(popoverElement) if (hash !== "") { const targetAnchor = hash.startsWith("#popover") ? hash : `#popover-${hash.slice(1)}` @@ -106,10 +115,23 @@ async function mouseEnterHandler( } } +function clearActivePopover() { + const allPopoverElements = document.querySelectorAll(".popover") + if (allPopoverElements) { + allPopoverElements.forEach((popoverElement) => + popoverElement.classList.remove("active-popover"), + ) + } +} + document.addEventListener("nav", () => { const links = [...document.getElementsByClassName("internal")] as HTMLAnchorElement[] for (const link of links) { + link.addEventListener("mouseleave", clearActivePopover) link.addEventListener("mouseenter", mouseEnterHandler) - window.addCleanup(() => link.removeEventListener("mouseenter", mouseEnterHandler)) + window.addCleanup(() => { + link.removeEventListener("mouseenter", mouseEnterHandler) + link.removeEventListener("mouseleave", clearActivePopover) + }) } }) diff --git a/quartz/components/styles/backlinks.scss b/quartz/components/styles/backlinks.scss index 71c13f04e..c8c862ff4 100644 --- a/quartz/components/styles/backlinks.scss +++ b/quartz/components/styles/backlinks.scss @@ -12,6 +12,8 @@ list-style: none; padding: 0; margin: 0.5rem 0; + height: 6rem; + overscroll-behavior: contain; & > li { & > a { diff --git a/quartz/components/styles/explorer.scss b/quartz/components/styles/explorer.scss index a87411b2d..55c43722f 100644 --- a/quartz/components/styles/explorer.scss +++ b/quartz/components/styles/explorer.scss @@ -118,6 +118,7 @@ button.desktop-explorer { list-style: none; margin: 0; padding: 0; + overscroll-behavior: contain; & li > a { color: var(--dark); diff --git a/quartz/components/styles/popover.scss b/quartz/components/styles/popover.scss index 872045a2c..70e1dd6d2 100644 --- a/quartz/components/styles/popover.scss +++ b/quartz/components/styles/popover.scss @@ -16,9 +16,12 @@ .popover { z-index: 999; - position: absolute; + position: fixed; overflow: visible; padding: 1rem; + left: 0; + top: 0; + will-change: transform; & > .popover-inner { position: relative; @@ -35,6 +38,7 @@ border-radius: 5px; box-shadow: 6px 6px 36px 0 rgba(0, 0, 0, 0.25); overflow: auto; + overscroll-behavior: contain; white-space: normal; user-select: none; cursor: default; @@ -77,7 +81,7 @@ } } -a:hover .popover, +.active-popover, .popover:hover { animation: dropin 0.3s ease; animation-fill-mode: forwards; diff --git a/quartz/components/styles/toc.scss b/quartz/components/styles/toc.scss index d544d0e99..bf1bc223d 100644 --- a/quartz/components/styles/toc.scss +++ b/quartz/components/styles/toc.scss @@ -50,6 +50,8 @@ ul.toc-content { position: relative; margin: 0.5rem 0; padding: 0; + height: 5rem; + overscroll-behavior: contain; list-style: none; & > li > a {