blob: 665e933a613f6fa0430a7c7d9007a659d9d9336c [file] [log] [blame]
/**
* @module infra-sk/modules/theme-chooser-sk
* @description <h2><code>theme-chooser-sk</code></h2>
*
* <p>
* The <theme-chooser-sk> custom element. Imports a default and darkmode color
* palette and provides a toggle to swap between them. To use the themes,
* elements in the page should set colors via the variable provided in
* infra-sk/modules/theme-chooser-sk/theme-chooser-sk.scss
* Such as --primary, --on-primary, --background, --on-background, etc. Some
* additional classes are provided for convenience (primary-container-theme-sk,
* secondary-container-theme-sk, surface, etc)
* </p>
*
* <p>
* To change the color themes override the css variables in a ':root' selector.
* </p>
*
* @evt theme-chooser-toggle Sent when the theme has changed. The detail contains
* the darkmode value:
*
* <pre>
* detail {
* darkmode: true,
* }
* </pre>
*
*/
import { define } from 'elements-sk/define';
import { html } from 'lit-html';
import { ElementSk } from '../ElementSk';
import 'elements-sk/icon/invert-colors-icon-sk';
// Class applied to <body> to enable darkmode, and the key in localstorage to
// persist it.
const kDarkmodeClass = 'darkmode';
const template = () => html`<invert-colors-icon-sk></invert-colors-icon-sk>`;
// TODO(weston): Add logic to optionally automatically compute the --on-*
// colors to white or black based on color brightness for accessibility.
define('theme-chooser-sk', class extends ElementSk {
constructor() {
super(template);
}
connectedCallback() {
super.connectedCallback();
this._render();
this.addEventListener('click', this._toggleTheme);
// Set the class correctly based on window.localStorage.
this.darkmode = this.darkmode; // eslint-disable-line no-self-assign
}
_toggleTheme() {
this.darkmode = !this.darkmode;
}
/** @prop darkmode {bool} True if we are in darkmode. */
get darkmode() {
return window.localStorage.getItem(kDarkmodeClass) === 'true';
}
set darkmode(val) {
// Force to be a bool.
val = !!val;
window.localStorage.setItem(kDarkmodeClass, val);
document.body.classList.toggle(kDarkmodeClass, this.darkmode);
this.dispatchEvent(new CustomEvent('theme-chooser-toggle', { detail: { darkmode: val }, bubbles: true }));
}
});