From 71823c5f89ded843893a8b09ae63cee481153e15 Mon Sep 17 00:00:00 2001 From: tuscan-blue Date: Fri, 4 Apr 2025 21:17:44 +0800 Subject: [PATCH] fix(style): resolve popover overflow issue causing incomplete display --- quartz/components/scripts/popover.inline.ts | 33 +++++++++++++++++---- quartz/components/styles/popover.scss | 7 +++-- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/quartz/components/scripts/popover.inline.ts b/quartz/components/scripts/popover.inline.ts index 733779369..fb7c0d921 100644 --- a/quartz/components/scripts/popover.inline.ts +++ b/quartz/components/scripts/popover.inline.ts @@ -7,27 +7,33 @@ async function mouseEnterHandler( this: HTMLAnchorElement, { clientX, clientY }: { clientX: number; clientY: number }, ) { + inActivePopover() + const link = this + link.id = link.innerText 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: `translateY(${y}px)`, }) } - const hasAlreadyBeenFetched = () => - [...link.children].some((child) => child.classList.contains("popover")) + const prevPopoverElement = document.getElementById(`popover-${link.id}`) + 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) @@ -91,7 +97,9 @@ async function mouseEnterHandler( } setPosition(popoverElement) - link.appendChild(popoverElement) + popoverElement.id = `popover-${link.id}` + popoverElement?.classList.add("active-popover") + document.body.appendChild(popoverElement) if (hash !== "") { const heading = popoverInner.querySelector(hash) as HTMLElement | null @@ -102,10 +110,23 @@ async function mouseEnterHandler( } } +function inActivePopover() { + 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", inActivePopover) link.addEventListener("mouseenter", mouseEnterHandler) - window.addCleanup(() => link.removeEventListener("mouseenter", mouseEnterHandler)) + window.addCleanup(() => { + link.removeEventListener("mouseenter", mouseEnterHandler) + link.removeEventListener("mouseleave", inActivePopover) + }) } }) diff --git a/quartz/components/styles/popover.scss b/quartz/components/styles/popover.scss index 872045a2c..e070d59e5 100644 --- a/quartz/components/styles/popover.scss +++ b/quartz/components/styles/popover.scss @@ -16,9 +16,11 @@ .popover { z-index: 999; - position: absolute; + position: fixed; overflow: visible; padding: 1rem; + top: 0; + will-change: transform; & > .popover-inner { position: relative; @@ -35,6 +37,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 +80,7 @@ } } -a:hover .popover, +.active-popover, .popover:hover { animation: dropin 0.3s ease; animation-fill-mode: forwards;