diff --git a/web/src/components/MemoContent/MermaidBlock.tsx b/web/src/components/MemoContent/MermaidBlock.tsx index ca3bb575a..1f0d3afe4 100644 --- a/web/src/components/MemoContent/MermaidBlock.tsx +++ b/web/src/components/MemoContent/MermaidBlock.tsx @@ -7,23 +7,60 @@ interface MermaidBlockProps { className?: string; } -// Initialize mermaid with default configuration -mermaid.initialize({ - startOnLoad: false, - theme: "default", - securityLevel: "strict", - fontFamily: "inherit", -}); +/** + * Maps app theme to Mermaid theme + * @param appTheme - The app's theme value from data-theme attribute + * @returns Mermaid theme name + */ +const getMermaidTheme = (appTheme: string | null): "default" | "dark" => { + switch (appTheme) { + case "default-dark": + return "dark"; + case "default": + case "paper": + case "whitewall": + default: + return "default"; + } +}; + +/** + * Gets the current theme from the document + */ +const getCurrentTheme = (): string => { + return document.documentElement.getAttribute("data-theme") || "default"; +}; export const MermaidBlock = ({ children, className }: MermaidBlockProps) => { const containerRef = useRef(null); const [svg, setSvg] = useState(""); const [error, setError] = useState(""); + const [currentTheme, setCurrentTheme] = useState(getCurrentTheme()); // Extract the code element and its content const codeElement = children as React.ReactElement; const codeContent = String(codeElement?.props?.children || "").replace(/\n$/, ""); + // Watch for theme changes + useEffect(() => { + const observer = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.type === "attributes" && mutation.attributeName === "data-theme") { + const newTheme = getCurrentTheme(); + setCurrentTheme(newTheme); + } + }); + }); + + observer.observe(document.documentElement, { + attributes: true, + attributeFilter: ["data-theme"], + }); + + return () => observer.disconnect(); + }, []); + + // Render diagram when content or theme changes useEffect(() => { const renderDiagram = async () => { if (!codeContent || !containerRef.current) { @@ -34,6 +71,17 @@ export const MermaidBlock = ({ children, className }: MermaidBlockProps) => { // Generate a unique ID for this diagram const id = `mermaid-${Math.random().toString(36).substring(7)}`; + // Get the appropriate Mermaid theme for current app theme + const mermaidTheme = getMermaidTheme(currentTheme); + + // Initialize mermaid with current theme + mermaid.initialize({ + startOnLoad: false, + theme: mermaidTheme, + securityLevel: "strict", + fontFamily: "inherit", + }); + // Render the mermaid diagram const { svg: renderedSvg } = await mermaid.render(id, codeContent); setSvg(renderedSvg); @@ -45,7 +93,7 @@ export const MermaidBlock = ({ children, className }: MermaidBlockProps) => { }; renderDiagram(); - }, [codeContent]); + }, [codeContent, currentTheme]); // If there's an error, fall back to showing the code if (error) {