feat(theme): broadcast theme:change so SVG/canvas consumers can repaint (#1839)

`theme_controller#setTheme` already toggles `data-theme` on the
document element, but D3/SVG/canvas consumers that bake color into
attributes (`fill`, `stroke`, `stop-color`) can't observe a CSS
variable change — they need an imperative re-render hook.

Dispatch a `theme:change` CustomEvent on the document element after
the attribute flips, with `detail: { theme: "dark" | "light" }`.
Consumers subscribe via standard connect/disconnect listeners.

Refactor the if/else into a single path while at it — same behavior,
half the lines.

Closes #1764.
This commit is contained in:
Guillem Arias Fauste
2026-05-20 18:13:07 +02:00
committed by GitHub
parent e07d641ead
commit 272b8acd66

View File

@@ -39,15 +39,15 @@ export default class extends Controller {
}
}
// Sets or removes the data-theme attribute
// Sets the data-theme attribute and broadcasts a `theme:change` event so
// imperative consumers (D3/SVG/canvas) can repaint without polling.
setTheme(isDark) {
if (isDark) {
localStorage.theme = "dark";
document.documentElement.setAttribute("data-theme", "dark");
} else {
localStorage.theme = "light";
document.documentElement.setAttribute("data-theme", "light");
}
const theme = isDark ? "dark" : "light";
localStorage.theme = theme;
document.documentElement.setAttribute("data-theme", theme);
document.documentElement.dispatchEvent(
new CustomEvent("theme:change", { detail: { theme } }),
);
}
systemPrefersDark() {