diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro
index 4af5b1a..afdbe10 100644
--- a/src/layouts/Layout.astro
+++ b/src/layouts/Layout.astro
@@ -559,6 +559,29 @@ const setup = () => {
})
window.swup.hooks.on('content:replace', initCustomScrollbar)
window.swup.hooks.on('visit:start', (visit: {to: {url: string}}) => {
+ // 切页前断开 observer、关闭并清理 panel
+ // @ts-ignore
+ if (document.body.__copyPageObserver) {
+ // @ts-ignore
+ document.body.__copyPageObserver.disconnect();
+ // @ts-ignore
+ document.body.__copyPageObserver = undefined;
+ }
+ const copyPagePanel = document.getElementById('copy-page-panel');
+ if (copyPagePanel) {
+ copyPagePanel.classList.add('pointer-events-none', 'opacity-0', '-translate-y-1');
+ copyPagePanel.classList.remove('opacity-100', 'translate-y-0');
+ // 如果 panel 已被移到 body(portal 模式),直接移除
+ if (copyPagePanel.parentElement === document.body) {
+ copyPagePanel.remove();
+ }
+ }
+ const copyPageMenu = document.getElementById('copy-page-menu');
+ const copyPageArrow = copyPageMenu?.querySelector('.copy-page-arrow');
+ const copyPageSwitch = document.getElementById('copy-page-switch');
+ if (copyPageArrow) copyPageArrow.classList.remove('rotate-180');
+ if (copyPageSwitch) copyPageSwitch.setAttribute('aria-expanded', 'false');
+
// change banner height immediately when a link is clicked
const bodyElement = document.querySelector('body')
if (pathsEqual(visit.to.url, url('/'))) {
diff --git a/src/pages/posts/[...slug].astro b/src/pages/posts/[...slug].astro
index 1f7f581..aab9ef2 100644
--- a/src/pages/posts/[...slug].astro
+++ b/src/pages/posts/[...slug].astro
@@ -222,7 +222,7 @@ const isOutdated = entry.data.outdated;
-
+
{copyPageAiLinks.map((link) => (
{
setMenuOpen(panel.classList.contains('opacity-0'));
@@ -516,7 +535,7 @@ const isOutdated = entry.data.outdated;
try {
await navigator.clipboard.writeText(copyPageText);
copyLabel.textContent = '已复制';
- closeMenu();
+ setMenuOpen(false);
window.setTimeout(() => {
copyLabel.textContent = '复制页面';
}, 1500);
@@ -529,16 +548,29 @@ const isOutdated = entry.data.outdated;
}
});
+ // 当菜单按钮滚出视口(被 navbar 遮挡或滚到下方)时自动关闭 panel
+ if (document.body['__copyPageObserver']) {
+ document.body['__copyPageObserver'].disconnect();
+ }
+ document.body['__copyPageObserver'] = new IntersectionObserver((entries) => {
+ if (!entries[0].isIntersecting) {
+ setMenuOpen(false);
+ }
+ }, { rootMargin: '-80px 0px 0px 0px', threshold: 0 });
+ document.body['__copyPageObserver'].observe(menu);
+
if (!document.body.dataset.copyPageOutsideReady) {
document.body.dataset.copyPageOutsideReady = 'true';
document.addEventListener('click', (event) => {
const currentMenu = document.getElementById('copy-page-menu');
- const currentSwitch = document.getElementById('copy-page-switch');
const currentPanel = document.getElementById('copy-page-panel');
+ const currentSwitch = document.getElementById('copy-page-switch');
const currentArrow = currentMenu?.querySelector('.copy-page-arrow');
- if (!(event.target instanceof Node) || currentMenu?.contains(event.target)) {
- return;
- }
+ // 点击 menu 或 panel 内部时不关闭
+ if (!(event.target instanceof Node)) return;
+ if (currentMenu?.contains(event.target)) return;
+ if (currentPanel?.contains(event.target)) return;
+ // 关闭
currentPanel?.classList.add('pointer-events-none', 'opacity-0', '-translate-y-1');
currentPanel?.classList.remove('opacity-100', 'translate-y-0');
currentArrow?.classList.remove('rotate-180');