const themeToggle = document.createElement('template'); themeToggle.innerHTML = ` `; class ThemeToggle extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }).append(themeToggle.content.cloneNode(true)); this.isChecked = false; this.hasTheme = 'light'; this.toggleState = this.toggleState.bind(this); this.fireEvent = this.fireEvent.bind(this); this.handleThemeChange = this.handleThemeChange.bind(this); } static get observedAttributes() { return ['checked']; } daylight() { this.hasTheme = 'light'; document.body.dataset.theme = 'light'; this.setAttribute('aria-checked', 'false'); } nightlight() { this.hasTheme = 'dark'; document.body.dataset.theme = 'dark'; this.setAttribute('aria-checked', 'true'); } toggleState() { this.toggleAttribute('checked'); this.fireEvent(); } handleKeyDown(e) { if (e.key === ' ') { this.toggleState(); } } handleThemeChange(e) { if (e.detail.theme !== this.hasTheme) { if (e.detail.theme === 'dark') { this.setAttribute('checked', ''); } else { this.removeAttribute('checked'); } } } fireEvent() { this.dispatchEvent( new CustomEvent('themechange', { bubbles: true, composed: true, detail: { theme: this.hasTheme } }) ); } connectedCallback() { this.setAttribute('role', 'switch'); this.setAttribute('aria-label', 'theme toggle'); if (localStorage.getItem(`${window.location.hostname}-theme`) === "dark") { this.nightlight(); this.setAttribute('checked', ''); } else if (localStorage.getItem(`${window.location.hostname}-theme`) === "light") { this.daylight(); this.removeAttribute('checked'); } else { if (window.matchMedia(`(prefers-color-scheme: dark)`).matches) { this.nightlight(); this.setAttribute('checked', ''); } else { this.daylight(); this.removeAttribute('checked'); } } this.addEventListener("click", this.toggleState); this.addEventListener("keydown", this.handleKeyDown); document.addEventListener('themechange', this.handleThemeChange); } disconnectedCallback() { this.removeEventListener("click", this.toggleState); this.removeEventListener("keydown", this.handleKeyDown); document.removeEventListener('themechange', this.handleThemeChange); } attributeChangedCallback(name, oldVal, newVal) { if (name === 'checked') { if (this.hasAttribute('checked')) { this.nightlight(); localStorage.setItem(`${window.location.hostname}-theme`, "dark"); } else { this.daylight(); localStorage.setItem(`${window.location.hostname}-theme`, "light"); } } } } window.customElements.define('theme-toggle', ThemeToggle);