130 lines
3.5 KiB
JavaScript
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;
|
|
}
|
|
|
|
})(); |