diff --git a/src/components/Article.tsx b/src/components/Article.tsx index 08deeb2..6844ea0 100644 --- a/src/components/Article.tsx +++ b/src/components/Article.tsx @@ -7,6 +7,7 @@ export interface ArticleProps { section?: string; // 指定要显示的标题(不含 #) onLoaded?: () => void; onError?: (error: Error) => void; + class?: string; // 额外的 class 用于样式控制 } async function fetchArticleContent(params: { src: string; section?: string }): Promise { @@ -39,7 +40,7 @@ export const Article: Component = (props) => { }); return ( -
+
加载中...
diff --git a/src/components/md-link.tsx b/src/components/md-link.tsx index 9892941..c745d35 100644 --- a/src/components/md-link.tsx +++ b/src/components/md-link.tsx @@ -8,8 +8,10 @@ customElement("md-link", {}, (props, { element }) => { noShadowDOM(); const [showArticle, setShowArticle] = createSignal(false); + const [expanded, setExpanded] = createSignal(false); let articleContainer: HTMLDivElement | undefined; let disposeArticle: (() => void) | null = null; + let articleElement: HTMLElement | undefined; // 从 element 的 textContent 获取链接目标(支持 path#section 语法) const rawLinkSrc = element?.textContent?.trim() || ""; @@ -38,14 +40,20 @@ customElement("md-link", {}, (props, { element }) => { if (!parentP) return; if (showArticle()) { - // 隐藏文章 + // 隐藏文章 - 先折叠再移除 + setExpanded(false); if (articleContainer) { - if (disposeArticle) { - disposeArticle(); - disposeArticle = null; - } - articleContainer.remove(); - articleContainer = undefined; + articleContainer.style.height = '0'; + articleContainer.style.opacity = '0'; + setTimeout(() => { + if (disposeArticle) { + disposeArticle(); + disposeArticle = null; + } + articleContainer?.remove(); + articleContainer = undefined; + articleElement = undefined; + }, 300); } setShowArticle(false); } else { @@ -53,6 +61,10 @@ customElement("md-link", {}, (props, { element }) => { articleContainer = document.createElement("div"); articleContainer.classList.add("md-link-article"); articleContainer.classList.add("ml-4", "border-l-2", "border-gray-200", "pl-4"); + articleContainer.style.height = '0'; + articleContainer.style.opacity = '0'; + articleContainer.style.overflow = 'hidden'; + articleContainer.style.transition = 'height 0.3s ease, opacity 0.3s ease'; parentP.after(articleContainer); // 渲染 Article 组件 @@ -60,7 +72,19 @@ customElement("md-link", {}, (props, { element }) => {
console.log("Article loaded:", linkSrc)} + class="article-animate" + onLoaded={() => { + // 内容加载完成后,获取实际高度并展开 + requestAnimationFrame(() => { + articleElement = articleContainer?.querySelector('article[data-src]'); + if (articleElement) { + const height = articleElement.scrollHeight; + articleContainer!.style.height = `${height}px`; + articleContainer!.style.opacity = '1'; + setExpanded(true); + } + }); + }} onError={(err) => console.error("Article error:", err)} /> ), articleContainer);