diff --git a/src/common/di.config.ts b/src/common/di.config.ts
index c99d220..bf6d548 100644
--- a/src/common/di.config.ts
+++ b/src/common/di.config.ts
@@ -19,6 +19,7 @@ import { FitToScreenKeyListener as CenterDiagramKeyListener } from "./fitToScree
import { DiagramModificationCommandStack } from "./customCommandStack";
import "./commonStyling.css";
+import { LightDarkSwitch } from "./lightDarkSwitch";
export const commonModule = new ContainerModule((bind, unbind, isBound, rebind) => {
bind(ServerCommandPaletteActionProvider).toSelf().inSingletonScope();
@@ -33,6 +34,10 @@ export const commonModule = new ContainerModule((bind, unbind, isBound, rebind)
bind(TYPES.IUIExtension).toService(HelpUI);
bind(EDITOR_TYPES.DefaultUIElement).toService(HelpUI);
+ bind(LightDarkSwitch).toSelf().inSingletonScope();
+ bind(TYPES.IUIExtension).toService(LightDarkSwitch);
+ bind(EDITOR_TYPES.DefaultUIElement).toService(LightDarkSwitch);
+
bind(DynamicChildrenProcessor).toSelf().inSingletonScope();
unbind(TYPES.ICommandStack);
diff --git a/src/common/lightDarkSwitch.css b/src/common/lightDarkSwitch.css
new file mode 100644
index 0000000..7e5f62d
--- /dev/null
+++ b/src/common/lightDarkSwitch.css
@@ -0,0 +1,20 @@
+div.light-dark-switch {
+ left: 20px;
+ bottom: 70px;
+ padding: 10px 10px;
+}
+
+#light-dark-label #light-dark-button::before {
+ content: "";
+ background-image: url("@fortawesome/fontawesome-free/svgs/regular/moon.svg");
+ display: inline-block;
+ filter: invert(var(--dark-mode));
+ height: 16px;
+ width: 16px;
+ background-size: 16px 16px;
+ vertical-align: text-top;
+}
+
+#light-dark-switch:checked ~ label #light-dark-button::before {
+ background-image: url("@fortawesome/fontawesome-free/svgs/regular/sun.svg");
+}
diff --git a/src/common/lightDarkSwitch.ts b/src/common/lightDarkSwitch.ts
new file mode 100644
index 0000000..6e1eab8
--- /dev/null
+++ b/src/common/lightDarkSwitch.ts
@@ -0,0 +1,45 @@
+import { injectable } from "inversify";
+import "./lightDarkSwitch.css";
+import { AbstractUIExtension } from "sprotty";
+
+@injectable()
+export class LightDarkSwitch extends AbstractUIExtension {
+ static readonly ID = "light-dark-switch";
+ static useDarkMode = false;
+
+ id(): string {
+ return LightDarkSwitch.ID;
+ }
+ containerClass(): string {
+ return LightDarkSwitch.ID;
+ }
+ protected initializeContents(containerElement: HTMLElement): void {
+ containerElement.classList.add("ui-float");
+ containerElement.innerHTML = `
+
+
+ `;
+
+ const checkbox = containerElement.querySelector("#light-dark-switch") as HTMLInputElement;
+ checkbox.addEventListener("change", () => {
+ this.changeDarkMode(checkbox.checked);
+ });
+
+ // use the default browser theme
+ if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
+ checkbox.checked = true;
+ this.changeDarkMode(true);
+ }
+ }
+
+ private changeDarkMode(useDark: boolean) {
+ const rootElement = document.querySelector(":root") as HTMLElement;
+ const sprottyElement = document.querySelector("#sprotty") as HTMLElement;
+
+ const value = useDark ? "dark" : "light";
+ rootElement.setAttribute("data-theme", value);
+ sprottyElement.setAttribute("data-theme", value);
+ }
+}
diff --git a/src/theme.css b/src/theme.css
index c55dd6d..a6b6604 100644
--- a/src/theme.css
+++ b/src/theme.css
@@ -9,19 +9,17 @@
--dark-mode: 0;
}
-@media (prefers-color-scheme: dark) {
- :root {
- --color-foreground: #fff;
- --color-background: #000;
- --color-primary: #222;
- --color-valid: #0f0;
- --color-tool-palette-hover: #444;
- --color-tool-palette-selected: #555;
- --dark-mode: 1;
- }
+:root[data-theme="dark"] {
+ --color-foreground: #fff;
+ --color-background: #000;
+ --color-primary: #222;
+ --color-valid: #0f0;
+ --color-tool-palette-hover: #444;
+ --color-tool-palette-selected: #555;
+ --dark-mode: 1;
+}
- #sprotty div {
- /* Use default dark theme browser styles for scrollbars etc. inside all UI extensions */
- color-scheme: dark;
- }
+#sprotty[data-theme="dark"] div {
+ /* Use default dark theme browser styles for scrollbars etc. inside all UI extensions */
+ color-scheme: dark;
}