fix: Regression - invert SVGs in Dark Mode (#10695)

* initial implementation

* lint

* removed separate getThemeFilterValue function from renderElement

* removed BinaryFileData changes

* filter instead of css filter
This commit is contained in:
zsviczian
2026-01-24 13:00:14 +01:00
committed by GitHub
parent d5e37cda81
commit 60759d314d
3 changed files with 27 additions and 1 deletions
+2
View File
@@ -190,6 +190,8 @@ export const THEME = {
DARK: "dark",
} as const;
export const DARK_THEME_FILTER = "invert(93%) hue-rotate(180deg)";
export const FRAME_STYLE = {
strokeColor: "#bbb" as ExcalidrawElement["strokeColor"],
strokeWidth: 2 as ExcalidrawElement["strokeWidth"],
+16 -1
View File
@@ -14,6 +14,7 @@ import {
DEFAULT_REDUCED_GLOBAL_ALPHA,
ELEMENT_READY_TO_ERASE_OPACITY,
FRAME_STYLE,
DARK_THEME_FILTER,
MIME_TYPES,
THEME,
distance,
@@ -433,9 +434,22 @@ const drawElementOnCanvas = (
break;
}
case "image": {
context.save();
const cacheEntry =
element.fileId !== null
? renderConfig.imageCache.get(element.fileId)
: null;
const img = isInitializedImageElement(element)
? renderConfig.imageCache.get(element.fileId)?.image
? cacheEntry?.image
: undefined;
const shouldInvertImage =
renderConfig.theme === THEME.DARK &&
cacheEntry?.mimeType === MIME_TYPES.svg;
if (shouldInvertImage) {
context.filter = DARK_THEME_FILTER;
}
if (img != null && !(img instanceof Promise)) {
if (element.roundness && context.roundRect) {
context.beginPath();
@@ -472,6 +486,7 @@ const drawElementOnCanvas = (
} else {
drawImagePlaceholder(element, context);
}
context.restore();
break;
}
default: {
@@ -3,11 +3,13 @@ import {
MAX_DECIMALS_FOR_SVG_EXPORT,
SVG_NS,
THEME,
DARK_THEME_FILTER,
getFontFamilyString,
isRTL,
isTestEnv,
getVerticalOffset,
applyDarkModeFilter,
MIME_TYPES,
} from "@excalidraw/common";
import { normalizeLink, toValidURL } from "@excalidraw/common";
import { hashString } from "@excalidraw/element";
@@ -520,6 +522,13 @@ const renderElementToSvg = (
const g = svgRoot.ownerDocument.createElementNS(SVG_NS, "g");
if (
renderConfig.theme === THEME.DARK &&
fileData.mimeType === MIME_TYPES.svg
) {
g.setAttribute("filter", DARK_THEME_FILTER);
}
if (element.crop) {
const mask = svgRoot.ownerDocument.createElementNS(SVG_NS, "mask");
mask.setAttribute("id", `mask-image-crop-${element.id}`);