From b3cbc0e116c474d9875b895ac7d594b42c15b35a Mon Sep 17 00:00:00 2001
From: Tamara Steinwender <tamara.steinwender@tugraz.at>
Date: Tue, 1 Feb 2022 14:42:26 +0100
Subject: [PATCH] Remove color mode from app shell and add theme switcher
 webcomponent

---
 packages/app-shell/src/app-shell.js  |  13 +-
 packages/app-shell/src/color-mode.js | 254 ---------------------------
 2 files changed, 3 insertions(+), 264 deletions(-)
 delete mode 100644 packages/app-shell/src/color-mode.js

diff --git a/packages/app-shell/src/app-shell.js b/packages/app-shell/src/app-shell.js
index 10f0b664..c0878047 100644
--- a/packages/app-shell/src/app-shell.js
+++ b/packages/app-shell/src/app-shell.js
@@ -5,8 +5,8 @@ import {LanguageSelect} from '@dbp-toolkit/language-select';
 import {Icon} from '@dbp-toolkit/common';
 import {AuthKeycloak} from '@dbp-toolkit/auth';
 import {AuthMenuButton} from './auth-menu-button.js';
-import {ColorMode} from './color-mode.js';
 import {Notification} from '@dbp-toolkit/notification';
+import {ThemeSwitcher} from '@dbp-toolkit/theme-switcher';
 import * as commonStyles from '@dbp-toolkit/common/styles';
 import {classMap} from 'lit/directives/class-map.js';
 import {Router} from './router.js';
@@ -74,7 +74,6 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) {
 
         this.auth = {};
 
-        this.themes = "";
     }
 
     static get scopedElements() {
@@ -83,7 +82,7 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) {
           'dbp-build-info': BuildInfo,
           'dbp-auth-keycloak': AuthKeycloak,
           'dbp-auth-menu-button': AuthMenuButton,
-          'dbp-color-mode-button': ColorMode,
+          'dbp-theme-switcher': ThemeSwitcher,
           'dbp-notification': Notification,
           'dbp-icon': Icon,
           'dbp-matomo': MatomoElement,
@@ -260,8 +259,6 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) {
             buildTime: { type: String, attribute: "build-time" },
             env: { type: String },
             auth: { type: Object },
-            themes: { type: String, attribute: "themes" },
-            darkModeThemeOverride: {type: String, attribute: "dark-mode-theme-override"}
         };
     }
 
@@ -911,10 +908,6 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) {
             menuTemplates.push(html`<li><a @click="${(e) => this.onMenuItemClick(e)}" href="${this.router.getPathname({component: routingName})}" data-nav class="${getSelectClasses(routingName)}" title="${this.metaDataText(routingName, "description")}">${this.metaDataText(routingName, "short_name")}</a></li>`);
         }
 
-        const colorModeButton = this.darkModeThemeOverride !== undefined ?
-            html`<dbp-color-mode-button themes="${this.themes}" dark-mode-theme-override=${this.darkModeThemeOverride} lang="${this.lang}"></dbp-color-mode-button>` :
-            html`<dbp-color-mode-button themes="${this.themes}" lang="${this.lang}"></dbp-color-mode-button>`;
-
         const kc = this.keycloakConfig;
         return html`
             <slot class="${slotClassMap}"></slot>
@@ -926,7 +919,7 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) {
                     <header>
                         <slot name="header">
                             <div class="hd1-left">
-                                ${colorModeButton}
+                                <dbp-theme-switcher subscribe="themes,dark-mode-theme-override" lang="${this.lang}"></dbp-theme-switcher>
                                 <dbp-language-select id="lang-select" lang="${this.lang}"></dbp-language-select>
                             </div>
                             <div class="hd1-middle">
diff --git a/packages/app-shell/src/color-mode.js b/packages/app-shell/src/color-mode.js
deleted file mode 100644
index 89e02999..00000000
--- a/packages/app-shell/src/color-mode.js
+++ /dev/null
@@ -1,254 +0,0 @@
-import {html, css} from 'lit';
-import * as commonStyles from '@dbp-toolkit/common/styles';
-import {createInstance} from './i18n.js';
-import DBPLitElement from '@dbp-toolkit/common/dbp-lit-element';
-import {ScopedElementsMixin} from '@open-wc/scoped-elements';
-import {Icon} from '@dbp-toolkit/common';
-import {classMap} from 'lit/directives/class-map.js';
-
-
-export class ColorMode extends ScopedElementsMixin(DBPLitElement) {
-    constructor() {
-        super();
-
-        this._i18n = createInstance();
-        this.lang = this._i18n.language;
-        this.themes = [];
-        this.boundCloseAdditionalMenuHandler = this.hideModeMenu.bind(this);
-        this.detectBrowserDarkMode = false;
-        this.darkModeClass = "dark-theme";
-    }
-
-    static get properties() {
-        return {
-            ...super.properties,
-            lang: { type: String },
-            themes: { type: Array, attribute: "themes" },
-            darkModeThemeOverride: {type: String, attribute: "dark-mode-theme-override"}
-        };
-    }
-
-    static get scopedElements() {
-        return {
-            'dbp-icon': Icon
-        };
-    }
-
-
-    update(changedProperties) {
-        changedProperties.forEach((oldValue, propName) => {
-            if (propName === "lang") {
-                this._i18n.changeLanguage(this.lang);
-            }
-        });
-        super.update(changedProperties);
-    }
-
-    connectedCallback() {
-        super.connectedCallback();
-        this.updateComplete.then(() => {
-            console.log("------", this.darkModeThemeOverride);
-            if (typeof this.darkModeThemeOverride === "undefined") {
-                this.detectBrowserDarkMode = true;
-                console.log("darkMode on");
-            } else if ( this.darkModeThemeOverride === "") {
-                this.detectBrowserDarkMode = false;
-                console.log("darkMode off");
-            } else {
-                this.detectBrowserDarkMode = true;
-                this.darkModeClass = this.darkModeThemeOverride;
-            }
-            this.loadTheme("light-theme");
-            this.detectInitialMode();
-        });
-
-    }
-
-    detectInitialMode() {
-        //look for saved modes
-        let prefMode = localStorage.getItem('prefered-color-mode');
-        if (prefMode) {
-            // search for prefered mode
-            const theme = this.themes.find(theme => theme.class === prefMode);
-
-            if (theme) {
-                this.loadTheme(theme.class);
-            }
-            return;
-        }
-
-        if (this.detectBrowserDarkMode) {
-            //look for browser mode
-            const useDark = window.matchMedia("(prefers-color-scheme: dark)");
-            if (useDark.matches) {
-                // search for dark mode
-                const theme = this.themes.find(theme => theme.class === this.darkModeClass);
-
-                if (theme) {
-                    this.loadTheme(theme.class);
-                }
-            }
-        }
-    }
-
-    toggleModeMenu() {
-        const button = this.shadowRoot.querySelector(".mode-button");
-        if(!button) {
-            return;
-        }
-        if (button.classList.contains("active"))
-            button.classList.remove("active");
-        else
-            button.classList.add("active");
-        const menu = this.shadowRoot.querySelector("ul.extended-menu");
-        const menuStart = this.shadowRoot.querySelector(".mode-button");
-        if (menu === null || menuStart === null) {
-            return;
-        }
-
-        menu.classList.toggle('hidden');
-
-        if (!menu.classList.contains('hidden')) { // add event listener for clicking outside of menu
-            document.addEventListener('click', this.boundCloseAdditionalMenuHandler);
-            this.initateOpenAdditionalMenu = true;
-        }
-        else {
-            document.removeEventListener('click', this.boundCloseAdditionalMenuHandler);
-        }
-    }
-
-    hideModeMenu() {
-        if (this.initateOpenAdditionalMenu) {
-            this.initateOpenAdditionalMenu = false;
-            return;
-        }
-
-        const menu = this.shadowRoot.querySelector("ul.extended-menu");
-        if (menu && !menu.classList.contains('hidden'))
-            this.toggleModeMenu();
-    }
-
-    loadTheme(themeName) {
-        const button = this.shadowRoot.querySelector(".button-" + themeName);
-        const otherButtons = this.shadowRoot.querySelectorAll(".button-theme");
-        const body = this.shadowRoot.host.getRootNode({composed: true}).body;
-
-        if (button === null || otherButtons.length === 0 || body === null ) {
-            return;
-        }
-
-        otherButtons.forEach(button => button.classList.remove("active"));
-        button.classList.add("active");
-
-        if (!body.classList.contains(themeName)) {
-
-            this.themes.forEach(theme => {
-                body.classList.remove(theme.class);
-            });
-
-            body.classList.add(themeName);
-        }
-    }
-
-    saveTheme(themeName) {
-        //set active state
-        const browserModeDark = window.matchMedia("(prefers-color-scheme: dark)");
-        const browserModeLight = window.matchMedia("(prefers-color-scheme: light)");
-
-        if (themeName === "light-theme" && browserModeLight.matches) {
-            localStorage.removeItem('prefered-color-mode');
-        } else if (themeName === this.darkModeClass && browserModeDark.matches) {
-            localStorage.removeItem('prefered-color-mode');
-        } else {
-            localStorage.setItem('prefered-color-mode', themeName);
-        }
-    }
-
-    static get styles() {
-        return css`
-            ${commonStyles.getThemeCSS()}
-            ${commonStyles.getGeneralCSS()}
-            ${commonStyles.getButtonCSS()}
-           
-            
-            mode-button, button.button {
-                border: none;
-            }
-            
-            .active, .extended-menu li a.active dbp-icon {
-                color: var(--dbp-accent);
-            }
-            
-            .active {
-                font-weight: bolder;
-            }
-            
-            a:hover:not(.active) , .extended-menu li a:hover:not(.active) {
-              color: var(--dbp-hover-text);
-              background-color: var(--dbp-hover-base);
-              transition: none;
-            }
-            
-            a {
-              padding: 0.3em;
-              display: inline-block;
-              text-decoration: none;
-              transition: background-color 0.15s, color 0.15s;
-              color: var(--dbp-text);
-            }
-            
-            .extended-menu {
-              list-style: none;
-              border: var(--dbp-border);
-              position: absolute;
-              background-color: var(--dbp-base);
-              z-index: 1000;
-              border-radius: var(--dbp-border-radius);
-            }
-            
-            .extended-menu li {
-       
-              text-align: left;
-              min-width: 160px;
-            }
-            
-            .extended-menu li a {
-              white-space: nowrap;
-              overflow: hidden;
-              text-overflow: ellipsis;
-              padding: 12px 15px;
-              w1idth: 100%;
-              box-sizing: border-box;
-              text-align: left;
-              color: var(--dbp-text);
-              background: none;
-              display: block
-            }
-            
-            .icon {
-                margin-right: 10px;
-            }
-          
-        `;
-    }
-
-    render() {
-        const i18n = this._i18n;
-
-        return html`
-            <div class="${classMap({hidden: this.themes.length <= 1})}">
-                <a class="mode-button" title="${i18n.t('color-mode')}"
-                        @click="${() => {this.toggleModeMenu();}}"><dbp-icon name="contrast"></dbp-icon></a>
-                <ul class='extended-menu hidden'>
-                    ${this.themes.map(theme => html`
-                        <li class="" id="${theme.class}">
-                            <a class="button-theme button-${theme.class}" @click="${() => {this.loadTheme(theme.class); this.saveTheme(theme.class);}}" title="${theme.name}">
-                                <dbp-icon class="icon" name="${theme.icon}"></dbp-icon> ${theme.name}
-                            </a>
-                        </li>
-                    `)}
-                </ul>
-            </div>
-        `;
-    }
-}
\ No newline at end of file
-- 
GitLab