(() => {
const animation = 'linear .5s';
const color_scheme = 'color_scheme';
const color_scheme_attr = 'data-color-scheme';
const transition_attr = 'data-color-transition-enabled';
const prefers_dark_scheme = window.matchMedia('(prefers-color-scheme: dark)');
// Make sure we set the correct starting color scheme where loading
const override = localStorage.getItem(color_scheme);
if (override) {
document.body.setAttribute(color_scheme_attr, override);
}
setTimeout(() => {
if (document.body.scrollHeight > 30000) {
console.warn('document too large, disabling color theme transition animation');
return;
}
document.body.setAttribute(transition_attr, '');
}, 50);
const size = 1.25;
const styles = `
:host {
display: contents;
}
:host .wrapper {
width: ${size}rem;
height: ${size}rem;
padding: 0.5rem;
border-radius: 100%;
cursor: pointer;
overflow: hidden;
position: relative;
}
:host .wrapper .icons {
width: ${size * 2}rem;
display: flex;
flex-direction: row;
justify-content: space-between;
transition: transform ${animation};
pointer-events: none;
}
:host .wrapper .icons[data-mode='light'] {
/* */
}
:host .wrapper .icons[data-mode='dark'] {
transform: translateX(-${size}rem);
}
:host svg.icon {
--icon-size: ${size}rem;
transition: opacity ${animation};
}
:host svg.icon.sun {
color: var(--theme-text-body);
}
:host [data-mode='dark'] svg.icon.sun {
opacity: 0;
}
:host svg.icon.moon {
color: var(--theme-text-body);
}
:host [data-mode='light'] svg.icon.moon {
opacity: 0;
}
`;
const template = `
{{{ icons.sun }}}
{{{ icons.moon }}}
`;
customElements.define('color-scheme-toggle-button',
class ColorSchemeToggleButton extends HTMLElement {
#wrapper = null;
#icons = null;
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = template;
this.#wrapper = this.shadowRoot.querySelector('.wrapper');
this.#icons = this.shadowRoot.querySelector('.icons');
this.update_icons();
}
connectedCallback() {
this.addEventListener('click', this.onSelect);
this.addEventListener('keydown', this.onKeydown);
this.addEventListener('keyup', this.onKeyup);
}
disconnectedCallback() {
this.removeEventListener('click', this.onSelect);
this.removeEventListener('keydown', this.onKeydown);
this.removeEventListener('keyup', this.onKeyup);
}
onKeydown = (/** @type KeyboardEvent */ event) => {
if (event.keyCode === 32) {
event.preventDefault();
}
if (event.keyCode === 13) {
event.preventDefault();
this.onSelect();
}
};
onKeyup = (/** @type KeyboardEvent */ event) => {
if (event.keyCode === 32) {
event.preventDefault();
this.onSelect();
}
};
onSelect = () => {
toggle();
this.update_icons();
};
update_icons() {
const current = get_current();
this.#icons.setAttribute('data-mode', current);
this.#wrapper.setAttribute('aria-pressed', current === 'dark');
}
}
);
function get_current() {
const override = localStorage.getItem(color_scheme);
if (override) {
return override;
}
return prefers_dark_scheme.matches ? 'dark' : 'light';
}
function toggle() {
if (document.body.hasAttribute(color_scheme_attr)) {
localStorage.removeItem(color_scheme);
document.body.removeAttribute(color_scheme_attr);
}
else {
const preference = prefers_dark_scheme.matches ? 'light' : 'dark';
localStorage.setItem(color_scheme, preference);
document.body.setAttribute(color_scheme_attr, preference);
}
}
})();