Skip to content
Snippets Groups Projects
Commit b3cbc0e1 authored by Steinwender, Tamara's avatar Steinwender, Tamara
Browse files

Remove color mode from app shell and add theme switcher webcomponent

parent 4807c867
No related branches found
No related tags found
No related merge requests found
Pipeline #85986 failed
......@@ -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">
......
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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment