UNPKG

@alec.brunelle/darkmode-js

Version:

🌓 Add darkmode / nightmode to your website in a few seconds

209 lines (179 loc) • 5.91 kB
export const IS_BROWSER = typeof window !== "undefined"; export default class Darkmode { constructor(options) { if (!IS_BROWSER) { return; } const bottom = (options && options.bottom) || "32px"; const right = (options && options.right) || "32px"; const left = (options && options.left) || "unset"; const time = (options && options.time) || "0.3s"; const mixColor = (options && options.mixColor) || "#fff"; const backgroundColor = (options && options.backgroundColor) || "#fff"; const buttonColorDark = (options && options.buttonColorDark) || "#100f2c"; const buttonColorLight = (options && options.buttonColorLight) || "#fff"; const label = (options && options.label) || ""; const saveInCookies = options && options.saveInCookies; /* eslint-disable */ const autoMatchOsTheme = options && options.autoMatchOsTheme === false ? false : true; /* eslint-enable */ const css = ` .darkmode-layer { position: fixed; pointer-events: none; background: ${mixColor}; transition: all ${time} ease; mix-blend-mode: difference; } .darkmode-layer--button { width: 2.9rem; height: 2.9rem; border-radius: 50%; right: ${right}; bottom: ${bottom}; left: ${left}; } .darkmode-layer--simple { width: 100%; height: 100%; top: 0; left: 0; transform: scale(1) !important; } .darkmode-layer--expanded { transform: scale(100); border-radius: 0; } .darkmode-layer--no-transition { transition: none; } .darkmode-toggle { background: ${buttonColorDark}; width: 3rem; height: 3rem; position: fixed; border-radius: 50%; right: ${right}; bottom: ${bottom}; left: ${left}; cursor: pointer; transition: all 0.5s ease; display: flex; justify-content: center; align-items: center; } .darkmode-toggle--white { background: ${buttonColorLight}; } .darkmode-background { background: ${backgroundColor}; position: fixed; pointer-events: none; z-index: -10; width: 100%; height: 100%; top: 0; left: 0; } img, .darkmode-ignore { isolation: isolate; display: inline-block; } @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { .darkmode-toggle {display: none !important} } @supports (-ms-ime-align:auto), (-ms-accelerator:true) { .darkmode-toggle {display: none !important} } `; const layer = document.createElement("div"); const button = document.createElement("div"); const background = document.createElement("div"); button.innerHTML = label; layer.classList.add("darkmode-layer"); background.classList.add("darkmode-background"); const darkmodeActivated = window.localStorage.getItem("darkmode") === "true"; const preferedThemeOs = autoMatchOsTheme && window.matchMedia("(prefers-color-scheme: dark)").matches; const darkmodeNeverActivatedByAction = window.localStorage.getItem("darkmode") === null; if ( (darkmodeActivated === true && saveInCookies) || (darkmodeNeverActivatedByAction && preferedThemeOs) ) { layer.classList.add( "darkmode-layer--expanded", "darkmode-layer--simple", "darkmode-layer--no-transition" ); button.classList.add("darkmode-toggle--white"); document.body.classList.add("darkmode--activated"); } document.body.insertBefore(button, document.body.firstChild); document.body.insertBefore(layer, document.body.firstChild); document.body.insertBefore(background, document.body.firstChild); this.addStyle(css); this.button = button; this.layer = layer; this.saveInCookies = saveInCookies; this.time = time; } addStyle(css) { const linkElement = document.createElement("link"); linkElement.setAttribute("rel", "stylesheet"); linkElement.setAttribute("type", "text/css"); linkElement.setAttribute( "href", "data:text/css;charset=UTF-8," + encodeURIComponent(css) ); document.head.appendChild(linkElement); } showWidget() { if (!IS_BROWSER) { return; } const button = this.button; const layer = this.layer; const time = parseFloat(this.time) * 1000; button.classList.add("darkmode-toggle"); layer.classList.add("darkmode-layer--button"); button.addEventListener("click", () => { const isDarkmode = this.isActivated(); if (!isDarkmode) { layer.classList.add("darkmode-layer--expanded"); setTimeout(() => { layer.classList.add("darkmode-layer--no-transition"); layer.classList.add("darkmode-layer--simple"); }, time); } else { layer.classList.remove("darkmode-layer--simple"); setTimeout(() => { layer.classList.remove("darkmode-layer--no-transition"); layer.classList.remove("darkmode-layer--expanded"); }, 1); } button.classList.toggle("darkmode-toggle--white"); document.body.classList.toggle("darkmode--activated"); window.localStorage.setItem("darkmode", !isDarkmode); }); } toggle() { if (!IS_BROWSER) { return; } const layer = this.layer; const isDarkmode = this.isActivated(); layer.classList.toggle("darkmode-layer--simple"); document.body.classList.toggle("darkmode--activated"); window.localStorage.setItem("darkmode", !isDarkmode); } isActivated() { if (!IS_BROWSER) { return null; } return document.body.classList.contains("darkmode--activated"); } }