dashboard/templates/color-theme-controls.js

130 lines
3.5 KiB
JavaScript

(() => {
const color_theme = 'color_theme';
const color_contrast = 'color_contrast';
const color_theme_attr = 'data-color-theme';
const color_contrast_attr = 'data-color-contrast';
const override_theme = localStorage.getItem(color_theme);
const override_contrast = localStorage.getItem(color_contrast);
if (override_theme) {
document.body.setAttribute(color_theme_attr, override_theme);
}
if (override_contrast) {
document.body.setAttribute(color_contrast_attr, override_contrast);
}
const template = `
<link rel="stylesheet" href="/typography.css">
<link rel="stylesheet" href="/color-theme-controls.css">
<div class="popup" title="Color Theme and Contrast Controls">
<fieldset class="theme radio">
<legend>Color Theme</legend>
<label>
<input type="radio" name="color_theme" value="auto" ${checked_if(! override_theme)}>
<span>Auto</span>
</label>
<label>
<input type="radio" name="color_theme" value="light" ${checked_if(override_theme === 'light')}>
<span>Light</span>
</label>
<label>
<input type="radio" name="color_theme" value="dark" ${checked_if(override_theme === 'dark')}>
<span>Dark</span>
</label>
</fieldset>
<fieldset class="contrast radio">
<legend>Color Contrast</legend>
<label>
<input type="radio" name="color_contrast" value="less" ${checked_if(override_contrast === 'less')}>
<span>Less Contrast</span>
</label>
<label>
<input type="radio" name="color_contrast" value="default" ${checked_if(! override_contrast)}>
<span>Default</span>
</label>
<label>
<input type="radio" name="color_contrast" value="more" ${checked_if(override_contrast === 'more')}>
<span>More Contrast</span>
</label>
</fieldset>
</div>
`;
customElements.define('color-theme-and-contrast-controls',
class ColorThemeToggleButton extends HTMLElement {
#popup = null;
#theme_inputs = null;
#contrast_inputs = null;
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = template;
this.#popup = this.shadowRoot.querySelector('.popup');
this.#theme_inputs = this.#popup.querySelectorAll('.theme input');
this.#contrast_inputs = this.#popup.querySelectorAll('.contrast input');
}
connectedCallback() {
this.#popup.addEventListener('change', this.#onChange);
}
disconnectedCallback() {
this.#popup.removeEventListener('change', this.#onChange);
}
#onChange = () => {
const theme = this.#theme_input_value;
const contrast = this.#contrast_input_value;
if (theme === 'auto') {
localStorage.removeItem(color_theme);
document.body.removeAttribute(color_theme_attr);
}
else {
localStorage.setItem(color_theme, theme);
document.body.setAttribute(color_theme_attr, theme);
}
if (contrast === 'default') {
localStorage.removeItem(color_contrast);
document.body.removeAttribute(color_contrast_attr);
}
else {
localStorage.setItem(color_contrast, contrast);
document.body.setAttribute(color_contrast_attr, theme);
}
};
get #theme_input_value() {
return radio_value(this.#theme_inputs, 'auto');
}
get #contrast_input_value() {
return radio_value(this.#contrast_inputs, 'auto');
}
}
);
function checked_if(condition) {
return condition ? 'checked' : '';
}
function radio_value(inputs, default_value) {
inputs = [ ...inputs ];
for (const input of inputs) {
if (input.checked) {
return input.value;
}
}
return default_value;
}
})();