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; }