diff --git a/website/src/components/Extras/Frame/Frame.tsx b/website/src/components/Extras/Frame/Frame.tsx
index 45b7fae97..4c4ed60ea 100644
--- a/website/src/components/Extras/Frame/Frame.tsx
+++ b/website/src/components/Extras/Frame/Frame.tsx
@@ -3,7 +3,38 @@ import styles from "./Frame.module.css";
import clsx from "clsx";
import OgImage from "../../OgImage";
-function extractImagesFromParagraph(children: React.ReactNode): {
+// Adds className to img elements so it persists when medium-zoom clones them
+function addClassToImages(children: React.ReactNode, className?: string): React.ReactNode {
+ if (!className) return children;
+
+ if (React.isValidElement(children)) {
+ if (children.type === "img") {
+ return React.cloneElement(children, {
+ className: clsx(children.props.className, className),
+ });
+ }
+ if (children.props?.children) {
+ return React.cloneElement(children, {
+ children: addClassToImages(children.props.children, className),
+ });
+ }
+ }
+
+ if (Array.isArray(children)) {
+ return children.map((child, i) =>
+ React.isValidElement(child)
+ ? React.cloneElement(addClassToImages(child, className) as React.ReactElement, { key: i })
+ : child
+ );
+ }
+
+ return children;
+}
+
+function extractImagesFromParagraph(
+ children: React.ReactNode,
+ className?: string
+): {
content: React.ReactNode;
single: boolean;
} {
@@ -15,7 +46,7 @@ function extractImagesFromParagraph(children: React.ReactNode): {
const processedChildren = pChildren.map((child) => {
if (React.isValidElement(child) && child.type === "figure") {
return React.isValidElement(child) ? (
-
{child.props?.children}
+ {addClassToImages(child.props?.children, className)}
) : (
child
);
@@ -27,7 +58,7 @@ function extractImagesFromParagraph(children: React.ReactNode): {
if (React.isValidElement(pChildren) && pChildren.type === "figure") {
return {
- content: {pChildren.props?.children}
,
+ content: {addClassToImages(pChildren.props?.children, className)}
,
single,
};
}
@@ -37,9 +68,9 @@ function extractImagesFromParagraph(children: React.ReactNode): {
return {
content:
React.isValidElement(children) && children.type === "figure" ? (
- {children.props?.children}
+ {addClassToImages(children.props?.children, className)}
) : (
- children
+ addClassToImages(children, className)
),
single: false,
};
@@ -77,12 +108,14 @@ export default function Frame({
caption,
children,
ogImage = false,
+ className,
}: {
caption?: string;
children: React.ReactNode;
ogImage?: boolean;
+ className?: string;
}) {
- const { content: processedChildren, single } = extractImagesFromParagraph(children);
+ const { content: processedChildren, single } = extractImagesFromParagraph(children, className);
const ogImageSrc = ogImage ? extractFirstImageSrc(children) : undefined;
return (
diff --git a/website/src/css/customizations/_site.scss b/website/src/css/customizations/_site.scss
index 9e4928ad4..0dc6114c8 100644
--- a/website/src/css/customizations/_site.scss
+++ b/website/src/css/customizations/_site.scss
@@ -215,3 +215,10 @@ This file contains site-wide structural stylings. That includes sidebars, drop-d
.pagination-nav__link:hover {
background: color-mix(in srgb, var(--ifm-card-background-color) 60%, transparent);
}
+
+// Diagram images: invert colors in dark mode for visibility
+// Target both wrapper approach and direct img.diagram class (for medium-zoom cloned images)
+[data-theme="dark"] .diagram img,
+[data-theme="dark"] img.diagram {
+ filter: invert(1) hue-rotate(180deg);
+}