I have created a custom switch theme feature that is dynamic so that users can add themes with one color. Here, I am having difficulty injecting the theme_switcher belonging to erpnext.
The following is my CSS code, Should I include root:?
body {
background-color: var(--bg-color);
color: var(--text-color);
}
.sidebar {
background-color: var(--sidebar-bg);
color: var(--sidebar-text);
}
.sidebar a:hover {
background-color: var(--sidebar-hover-bg);
color: var(--sidebar-hover-text);
}
.navbar {
background-color: var(--navbar-bg);
color: var(--navbar-text);
}
.card {
background-color: var(--card-bg);
border: 1px solid var(--card-border);
box-shadow: 0 2px 4px var(--card-shadow);
}
.btn-primary {
background-color: var(--btn-primary-bg);
color: var(--btn-primary-color);
border: 1px solid var(--btn-primary-border);
}
.btn-primary:hover {
background-color: var(--btn-primary-hover-bg);
}
This is my JS code for performing the injection.
function inject_theme_style() {
const $body = $("body");
if ($body.data("custom-theme-injected")) {
console.log(" Theme already injected.");
return;
}
$body.data("custom-theme-injected", true);
console.log("inject_theme_style: start injecting");
frappe.call({
method: "custom_ui.custom_ui.doctype.ui_theme.ui_theme.get_active_theme",
callback: function (r) {
if (!r.message || !r.message.variables) return;
let vars = r.message.variables;
if (typeof vars === "string") {
try {
vars = JSON.parse(vars);
} catch (e) {
console.warn(" Parsing error. Using empty vars");
vars = {};
}
}
const $style = $("<style id='custom-theme-style'></style>");
let cssVars = ":root {\n";
for (const key in vars) {
if (Object.hasOwn(vars, key)) {
cssVars += ` ${key}: ${vars[key]};\n`;
}
}
cssVars += "}";
$style.text(cssVars);
$("head").append($style);
console.log(`Tema '${r.message.theme_name}' berhasil diinject!`);
}
});
}
window.reload_custom_theme_style = function () {
$("#custom-theme-style").remove();
$("body").removeData("custom-theme-injected");
inject_theme_style();
};
frappe.realtime.on("custom_theme_updated", () => {
console.log("Theme updated. Reloading...");
window.reload_custom_theme_style();
});
frappe.after_ajax(() => {
setTimeout(() => {
const interval = setInterval(() => {
if ($("body").length) {
clearInterval(interval);
console.log("DOM ready, injecting theme...");
inject_theme_style();
}
}, 200);
}, 500);
});
frappe.router.on("change", () => {
if (frappe.get_route()[0] === "app" || frappe.get_route()[0] === "desk") {
window.reload_custom_theme_style();
}
});