99 lines
2.5 KiB
JavaScript
99 lines
2.5 KiB
JavaScript
// For syntax highlighting only
|
||
const html = String.raw;
|
||
|
||
class ThemeToggle extends HTMLElement {
|
||
constructor() {
|
||
super();
|
||
|
||
this.STORAGE_KEY = 'user-color-scheme';
|
||
this.COLOR_MODE_KEY = '--color-mode';
|
||
}
|
||
|
||
connectedCallback() {
|
||
this.render();
|
||
}
|
||
|
||
getCSSCustomProp(propKey) {
|
||
let response = getComputedStyle(document.documentElement).getPropertyValue(propKey);
|
||
|
||
// Tidy up the string if there’s something to work with
|
||
if (response.length) {
|
||
response = response.replace(/\'|"/g, '').trim();
|
||
}
|
||
|
||
// Return the string response by default
|
||
return response;
|
||
}
|
||
|
||
applySetting(passedSetting) {
|
||
let currentSetting = passedSetting || localStorage.getItem(this.STORAGE_KEY);
|
||
|
||
if (currentSetting) {
|
||
document.documentElement.setAttribute('data-user-color-scheme', currentSetting);
|
||
this.setButtonLabelAndStatus(currentSetting);
|
||
} else {
|
||
this.setButtonLabelAndStatus(this.getCSSCustomProp(this.COLOR_MODE_KEY));
|
||
}
|
||
}
|
||
|
||
toggleSetting() {
|
||
let currentSetting = localStorage.getItem(this.STORAGE_KEY);
|
||
|
||
switch (currentSetting) {
|
||
case null:
|
||
currentSetting =
|
||
this.getCSSCustomProp(this.COLOR_MODE_KEY) === 'dark' ? 'light' : 'dark';
|
||
break;
|
||
case 'light':
|
||
currentSetting = 'dark';
|
||
break;
|
||
case 'dark':
|
||
currentSetting = 'light';
|
||
break;
|
||
}
|
||
|
||
localStorage.setItem(this.STORAGE_KEY, currentSetting);
|
||
|
||
return currentSetting;
|
||
}
|
||
|
||
setButtonLabelAndStatus(currentSetting) {
|
||
this.modeToggleButton.innerText = `${
|
||
currentSetting === 'dark' ? 'Light' : 'Dark'
|
||
} theme`;
|
||
this.modeStatusElement.innerText = `Color mode is now "${currentSetting}"`;
|
||
}
|
||
|
||
render() {
|
||
this.innerHTML = html`
|
||
<div class="[ theme-toggle ] [ md:ta-right gap-top-500 ]">
|
||
<div role="status" class="[ visually-hidden ][ js-mode-status ]"></div>
|
||
<button class="[ button ] [ font-base text-base weight-bold ] [ js-mode-toggle ]">
|
||
Dark theme
|
||
</button>
|
||
</div>
|
||
`;
|
||
|
||
this.afterRender();
|
||
}
|
||
|
||
afterRender() {
|
||
this.modeToggleButton = document.querySelector('.js-mode-toggle');
|
||
this.modeStatusElement = document.querySelector('.js-mode-status');
|
||
|
||
this.modeToggleButton.addEventListener('click', evt => {
|
||
evt.preventDefault();
|
||
|
||
this.applySetting(this.toggleSetting());
|
||
});
|
||
|
||
this.applySetting();
|
||
}
|
||
}
|
||
|
||
if ('customElements' in window) {
|
||
customElements.define('theme-toggle', ThemeToggle);
|
||
}
|
||
|
||
export default ThemeToggle;
|