✨ feat(theme-switcher): add theme reset button (#198)
This commit is contained in:
parent
c7bd9b36ce
commit
afbf4017e2
@ -1,7 +1,7 @@
|
|||||||
+++
|
+++
|
||||||
title = "Sense JavaScript obligatori"
|
title = "Sense JavaScript obligatori"
|
||||||
date = 2023-01-06
|
date = 2023-01-06
|
||||||
updated = 2023-09-01
|
updated = 2023-10-06
|
||||||
description = "JavaScript només s'utilitza quan HTML i CSS no són suficients."
|
description = "JavaScript només s'utilitza quan HTML i CSS no són suficients."
|
||||||
|
|
||||||
[taxonomies]
|
[taxonomies]
|
||||||
@ -16,7 +16,7 @@ Aquest tema no requereix JavaScript obligatori. Opcionalment, pot carregar una q
|
|||||||
|
|
||||||
## Opcions habilitades globalment
|
## Opcions habilitades globalment
|
||||||
|
|
||||||
- L'**interruptor de mode clar/fosc** es pot habilitar configurant `theme_switcher = true` a la secció `[extra]` del teu `config.toml` (~900 bytes de JavaScript).
|
- L'**interruptor de mode clar/fosc** es pot habilitar configurant `theme_switcher = true` a la secció `[extra]` del teu `config.toml` (~1KB de JavaScript).
|
||||||
|
|
||||||
- **Decodificació de correu electrònic** (~400 bytes). Per protegir contra robots de correu brossa, pots configurar `encode_plaintext_email = true`. Si el teu lloc web està en un repositori públic, considera utilitzar el teu `email` com una cadena codificada en base64[^1].
|
- **Decodificació de correu electrònic** (~400 bytes). Per protegir contra robots de correu brossa, pots configurar `encode_plaintext_email = true`. Si el teu lloc web està en un repositori públic, considera utilitzar el teu `email` com una cadena codificada en base64[^1].
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
+++
|
+++
|
||||||
title = "Sin JavaScript obligatorio"
|
title = "Sin JavaScript obligatorio"
|
||||||
date = 2023-01-06
|
date = 2023-01-06
|
||||||
updated = 2023-09-01
|
updated = 2023-10-06
|
||||||
description = "JavaScript solo se utiliza cuando HTML y CSS no son suficientes."
|
description = "JavaScript solo se utiliza cuando HTML y CSS no son suficientes."
|
||||||
|
|
||||||
[taxonomies]
|
[taxonomies]
|
||||||
@ -16,7 +16,7 @@ Este tema no requiere JavaScript de manera obligatoria. Opcionalmente, puede car
|
|||||||
|
|
||||||
## Opciones habilitadas globalmente
|
## Opciones habilitadas globalmente
|
||||||
|
|
||||||
- El **interruptor de modo claro/oscuro** puede habilitarse configurando `theme_switcher = true` en la sección `[extra]` de tu `config.toml` (~900 bytes de JavaScript).
|
- El **interruptor de modo claro/oscuro** puede habilitarse configurando `theme_switcher = true` en la sección `[extra]` de tu `config.toml` (~1KB de JavaScript).
|
||||||
|
|
||||||
- **Descodificación de correo electrónico** (~400 bytes). Para proteger contra bots que recopilan correos electrónicos desde tu sitio web, puedes configurar `encode_plaintext_email = true`. Si tu sitio está en un repositorio público, para mayor protección, considera configurar tu `email` como una cadena codificada en base64[^1].
|
- **Descodificación de correo electrónico** (~400 bytes). Para proteger contra bots que recopilan correos electrónicos desde tu sitio web, puedes configurar `encode_plaintext_email = true`. Si tu sitio está en un repositorio público, para mayor protección, considera configurar tu `email` como una cadena codificada en base64[^1].
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
+++
|
+++
|
||||||
title = "No mandatory JavaScript"
|
title = "No mandatory JavaScript"
|
||||||
date = 2023-01-06
|
date = 2023-01-06
|
||||||
updated = 2023-09-01
|
updated = 2023-10-06
|
||||||
description = "JavaScript is only used when HTML and CSS aren't enough."
|
description = "JavaScript is only used when HTML and CSS aren't enough."
|
||||||
|
|
||||||
[taxonomies]
|
[taxonomies]
|
||||||
@ -16,7 +16,7 @@ This theme has no mandatory JavaScript. Optionally, it can load a minimal amount
|
|||||||
|
|
||||||
## Globally enabled settings
|
## Globally enabled settings
|
||||||
|
|
||||||
- The **light/dark mode switch** can be enabled by setting `theme_switcher = true` in the `[extra]` section of your `config.toml` (~900 bytes of JavaScript).
|
- The **light/dark mode switch** can be enabled by setting `theme_switcher = true` in the `[extra]` section of your `config.toml` (~1KB of JavaScript).
|
||||||
|
|
||||||
- **E-mail decoding** (~400 bytes). To protect against spambots scraping your e-mail from your website, you can set `encode_plaintext_email = true`. If your site is on a public repository, for extra protection, consider setting your `email` as a base64-encoded string[^1] directly.
|
- **E-mail decoding** (~400 bytes). To protect against spambots scraping your e-mail from your website, you can set `encode_plaintext_email = true`. If your site is on a public repository, for extra protection, consider setting your `email` as a base64-encoded string[^1] directly.
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ language_selection = "Selecció d'idioma"
|
|||||||
toggle_mode = "Canvia el mode $MODE" # $MODE will be replaced by a value (or both) below.
|
toggle_mode = "Canvia el mode $MODE" # $MODE will be replaced by a value (or both) below.
|
||||||
dark = "obscur"
|
dark = "obscur"
|
||||||
light = "clar"
|
light = "clar"
|
||||||
|
reset_mode = "Restableix el mode als valors predeterminats del sistema"
|
||||||
|
|
||||||
# Post metadata.
|
# Post metadata.
|
||||||
draft = "ESBORRANY"
|
draft = "ESBORRANY"
|
||||||
|
@ -30,6 +30,7 @@ language_selection = "Sprachauswahl"
|
|||||||
toggle_mode = "Wechsle in den $MODE Modus" # $MODE will be replaced by a value (or both) below.
|
toggle_mode = "Wechsle in den $MODE Modus" # $MODE will be replaced by a value (or both) below.
|
||||||
dark = "dunkel"
|
dark = "dunkel"
|
||||||
light = "hell"
|
light = "hell"
|
||||||
|
reset_mode = "Modus auf Betriebssystemstandard zurücksetzen"
|
||||||
|
|
||||||
# Post metadata.
|
# Post metadata.
|
||||||
draft = "ENTWURF"
|
draft = "ENTWURF"
|
||||||
|
@ -26,6 +26,7 @@ language_selection = "Language selection"
|
|||||||
toggle_mode = "Toggle $MODE mode" # $MODE will be replaced by a value (or both) below.
|
toggle_mode = "Toggle $MODE mode" # $MODE will be replaced by a value (or both) below.
|
||||||
dark = "dark"
|
dark = "dark"
|
||||||
light = "light"
|
light = "light"
|
||||||
|
reset_mode = "Reset mode to OS default"
|
||||||
|
|
||||||
# Post metadata.
|
# Post metadata.
|
||||||
draft = "DRAFT"
|
draft = "DRAFT"
|
||||||
|
@ -26,6 +26,7 @@ language_selection = "Selección de idioma"
|
|||||||
toggle_mode = "Cambiar a modo $MODE" # $MODE will be replaced by a value (or both) below.
|
toggle_mode = "Cambiar a modo $MODE" # $MODE will be replaced by a value (or both) below.
|
||||||
dark = "oscuro"
|
dark = "oscuro"
|
||||||
light = "claro"
|
light = "claro"
|
||||||
|
reset_mode = "Restablecer modo a configuración predeterminada del SO"
|
||||||
|
|
||||||
# Post metadata.
|
# Post metadata.
|
||||||
draft = "BORRADOR"
|
draft = "BORRADOR"
|
||||||
|
@ -30,6 +30,7 @@ language_selection = "Sélection de la langue"
|
|||||||
toggle_mode = "Basculer en mode $MODE" # $MODE will be replaced by a value (or both) below.
|
toggle_mode = "Basculer en mode $MODE" # $MODE will be replaced by a value (or both) below.
|
||||||
dark = "sombre"
|
dark = "sombre"
|
||||||
light = "clair"
|
light = "clair"
|
||||||
|
reset_mode = "Réinitialiser le mode aux paramètres par défaut du système"
|
||||||
|
|
||||||
# Post metadata.
|
# Post metadata.
|
||||||
draft = "BROUILLON"
|
draft = "BROUILLON"
|
||||||
|
@ -28,6 +28,7 @@ language_selection = "भाषा चयन"
|
|||||||
toggle_mode = "$MODE मोड में टॉगल करें" # $MODE will be replaced by a value (or both) below.
|
toggle_mode = "$MODE मोड में टॉगल करें" # $MODE will be replaced by a value (or both) below.
|
||||||
dark = "अंधेरा"
|
dark = "अंधेरा"
|
||||||
light = "रोशनी"
|
light = "रोशनी"
|
||||||
|
reset_mode = "मोड को ओएस डिफ़ॉल्ट पर रीसेट करें"
|
||||||
|
|
||||||
# Post metadata.
|
# Post metadata.
|
||||||
draft = "मसौदा"
|
draft = "मसौदा"
|
||||||
|
@ -26,6 +26,7 @@ language_selection = "Selezione della lingua"
|
|||||||
toggle_mode = "Passa alla modalità $MODE" # $MODE will be replaced by a value (or both) below.
|
toggle_mode = "Passa alla modalità $MODE" # $MODE will be replaced by a value (or both) below.
|
||||||
dark = "scuro"
|
dark = "scuro"
|
||||||
light = "chiaro"
|
light = "chiaro"
|
||||||
|
reset_mode = "Reimposta la modalità alle impostazioni predefinite del sistema operativo"
|
||||||
|
|
||||||
# Post metadata.
|
# Post metadata.
|
||||||
draft = "BOZZA"
|
draft = "BOZZA"
|
||||||
|
@ -30,6 +30,7 @@ language_selection = "言語選択"
|
|||||||
toggle_mode = "$MODE モードに切り替え" # $MODE will be replaced by a value (or both) below.
|
toggle_mode = "$MODE モードに切り替え" # $MODE will be replaced by a value (or both) below.
|
||||||
dark = "暗い"
|
dark = "暗い"
|
||||||
light = "明るい"
|
light = "明るい"
|
||||||
|
reset_mode = "モードをOSデフォルトにリセット"
|
||||||
|
|
||||||
# Post metadata.
|
# Post metadata.
|
||||||
draft = "ドラフト"
|
draft = "ドラフト"
|
||||||
|
@ -30,6 +30,7 @@ language_selection = "언어 선택"
|
|||||||
toggle_mode = "$MODE 모드로 전환" # $MODE will be replaced by a value (or both) below.
|
toggle_mode = "$MODE 모드로 전환" # $MODE will be replaced by a value (or both) below.
|
||||||
dark = "어두운"
|
dark = "어두운"
|
||||||
light = "밝은"
|
light = "밝은"
|
||||||
|
reset_mode = "모드를 OS 기본값으로 재설정"
|
||||||
|
|
||||||
# Post metadata.
|
# Post metadata.
|
||||||
draft = "임시 저장"
|
draft = "임시 저장"
|
||||||
|
@ -26,6 +26,7 @@ language_selection = "Seleção de idioma"
|
|||||||
toggle_mode = "Alternar para o modo $MODE" # $MODE will be replaced by a value (or both) below.
|
toggle_mode = "Alternar para o modo $MODE" # $MODE will be replaced by a value (or both) below.
|
||||||
dark = "escuro"
|
dark = "escuro"
|
||||||
light = "claro"
|
light = "claro"
|
||||||
|
reset_mode = "Repor o modo para o padrão do SO"
|
||||||
|
|
||||||
# Post metadata.
|
# Post metadata.
|
||||||
draft = "RASCUNHO"
|
draft = "RASCUNHO"
|
||||||
|
@ -26,6 +26,7 @@ language_selection = "Выбор языка"
|
|||||||
toggle_mode = "Переключить на режим $MODE" # $MODE will be replaced by a value (or both) below.
|
toggle_mode = "Переключить на режим $MODE" # $MODE will be replaced by a value (or both) below.
|
||||||
dark = "тёмный"
|
dark = "тёмный"
|
||||||
light = "светлый"
|
light = "светлый"
|
||||||
|
reset_mode = "Сбросить режим к настройкам ОС по умолчанию"
|
||||||
|
|
||||||
# Post metadata.
|
# Post metadata.
|
||||||
draft = "ЧЕРНОВИК"
|
draft = "ЧЕРНОВИК"
|
||||||
|
@ -30,6 +30,7 @@ language_selection = "Вибір мови"
|
|||||||
toggle_mode = "Перемкнути в режим $MODE" # $MODE will be replaced by a value (or both) below.
|
toggle_mode = "Перемкнути в режим $MODE" # $MODE will be replaced by a value (or both) below.
|
||||||
dark = "темний"
|
dark = "темний"
|
||||||
light = "світлий"
|
light = "світлий"
|
||||||
|
reset_mode = "Скинути режим до типових параметрів ОС"
|
||||||
|
|
||||||
# Post metadata.
|
# Post metadata.
|
||||||
draft = "ЧЕРНЕТКА"
|
draft = "ЧЕРНЕТКА"
|
||||||
|
@ -26,6 +26,7 @@ language_selection = "语言选择" # Machine translated.
|
|||||||
toggle_mode = "切换到$MODE模式" # $MODE will be replaced by a value (or both) below. Machine translated.
|
toggle_mode = "切换到$MODE模式" # $MODE will be replaced by a value (or both) below. Machine translated.
|
||||||
dark = "暗" # Machine translated.
|
dark = "暗" # Machine translated.
|
||||||
light = "亮" # Machine translated.
|
light = "亮" # Machine translated.
|
||||||
|
reset_mode = "重置为操作系统默认模式" # Machine translated.
|
||||||
|
|
||||||
# Post metadata.
|
# Post metadata.
|
||||||
draft = "草稿"
|
draft = "草稿"
|
||||||
|
@ -26,6 +26,7 @@ language_selection = "語言選擇" # Machine translated.
|
|||||||
toggle_mode = "切換到$MODE模式" # $MODE will be replaced by a value (or both) below. Machine translated.
|
toggle_mode = "切換到$MODE模式" # $MODE will be replaced by a value (or both) below. Machine translated.
|
||||||
dark = "暗" # Machine translated.
|
dark = "暗" # Machine translated.
|
||||||
light = "亮" # Machine translated.
|
light = "亮" # Machine translated.
|
||||||
|
reset_mode = "重置為操作系統預設模式" # Machine translated.
|
||||||
|
|
||||||
# Post metadata.
|
# Post metadata.
|
||||||
draft = "草稿"
|
draft = "草稿"
|
||||||
|
@ -11,3 +11,32 @@
|
|||||||
background: var(--meta-color);
|
background: var(--meta-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.theme-switcher-wrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-resetter {
|
||||||
|
-webkit-mask: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" %3E%3Cpath d="M295.87-193.869v-78.001h291.152q43.63 0 72.369-33.424 28.739-33.423 28.739-79.271t-28.739-79.391Q630.652-497.5 587.022-497.5H343.913l87.478 87.478-55.652 55.153L193.869-536.5l181.87-181.631 55.652 55.653-87.478 86.978h243.109q75.435 0 127.272 56.522 51.837 56.521 51.837 134.174 0 77.652-51.837 134.293-51.837 56.642-127.272 56.642H295.87Z"/%3E%3C/svg%3E');
|
||||||
|
position: absolute;
|
||||||
|
top: -0.6rem;
|
||||||
|
right: -0.6rem;
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s ease, visibility 0.3s ease;
|
||||||
|
transition-delay: 0.5s;
|
||||||
|
cursor: pointer;
|
||||||
|
background: var(--text-color);
|
||||||
|
width: 0.8rem;
|
||||||
|
height: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.theme-switcher-wrapper:hover .theme-resetter.has-custom-theme {
|
||||||
|
visibility: visible;
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 0.1s ease, visibility 0.1s ease;
|
||||||
|
transition-delay: 0s;
|
||||||
|
&:hover {
|
||||||
|
background: var(--meta-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
// Get the theme switcher button element.
|
// Get the theme switcher button elements.
|
||||||
const themeSwitcher = document.querySelector(".theme-switcher");
|
const themeSwitcher = document.querySelector(".theme-switcher");
|
||||||
|
const themeResetter = document.querySelector(".theme-resetter");
|
||||||
|
|
||||||
// Retrieve theme from either the localStorage or the data-theme attribute on the document element.
|
// Retrieve theme from either the localStorage or the data-theme attribute on the document element.
|
||||||
let currentTheme = localStorage.getItem("theme") || document.documentElement.getAttribute('data-theme');
|
let currentTheme = localStorage.getItem("theme") || document.documentElement.getAttribute('data-theme');
|
||||||
|
|
||||||
// Function to set theme
|
// Function to set theme.
|
||||||
function setTheme(theme, saveToLocalStorage = false) {
|
function setTheme(theme, saveToLocalStorage = false) {
|
||||||
document.documentElement.setAttribute("data-theme", theme);
|
document.documentElement.setAttribute("data-theme", theme);
|
||||||
currentTheme = theme;
|
currentTheme = theme;
|
||||||
@ -13,6 +14,12 @@ function setTheme(theme, saveToLocalStorage = false) {
|
|||||||
|
|
||||||
if (saveToLocalStorage) {
|
if (saveToLocalStorage) {
|
||||||
localStorage.setItem("theme", theme);
|
localStorage.setItem("theme", theme);
|
||||||
|
themeResetter.classList.add("has-custom-theme");
|
||||||
|
themeResetter.setAttribute("aria-hidden", "false");
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem("theme");
|
||||||
|
themeResetter.classList.remove("has-custom-theme");
|
||||||
|
themeResetter.setAttribute("aria-hidden", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dispatch a custom event for comment systems.
|
// Dispatch a custom event for comment systems.
|
||||||
@ -22,6 +29,12 @@ function setTheme(theme, saveToLocalStorage = false) {
|
|||||||
window.dispatchEvent(event);
|
window.dispatchEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resetTheme() {
|
||||||
|
const isSystemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||||
|
const defaultTheme = isSystemDark ? "dark" : "light";
|
||||||
|
setTheme(defaultTheme);
|
||||||
|
}
|
||||||
|
|
||||||
// Function to switch between dark and light themes.
|
// Function to switch between dark and light themes.
|
||||||
function switchTheme() {
|
function switchTheme() {
|
||||||
// Set the new theme based on the current theme.
|
// Set the new theme based on the current theme.
|
||||||
@ -31,6 +44,8 @@ function switchTheme() {
|
|||||||
|
|
||||||
// Initialize the theme switcher button.
|
// Initialize the theme switcher button.
|
||||||
themeSwitcher.addEventListener("click", switchTheme, false);
|
themeSwitcher.addEventListener("click", switchTheme, false);
|
||||||
|
themeResetter.addEventListener("click", resetTheme, false);
|
||||||
|
|
||||||
themeSwitcher.setAttribute("role", "button");
|
themeSwitcher.setAttribute("role", "button");
|
||||||
let togglePressed = currentTheme === "dark" ? "true" : "false";
|
let togglePressed = currentTheme === "dark" ? "true" : "false";
|
||||||
themeSwitcher.setAttribute("aria-pressed", togglePressed);
|
themeSwitcher.setAttribute("aria-pressed", togglePressed);
|
||||||
@ -40,3 +55,9 @@ window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", e =
|
|||||||
const newTheme = e.matches ? "dark" : "light";
|
const newTheme = e.matches ? "dark" : "light";
|
||||||
setTheme(newTheme);
|
setTheme(newTheme);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (localStorage.getItem("theme")) {
|
||||||
|
themeResetter.classList.add("has-custom-theme");
|
||||||
|
} else {
|
||||||
|
themeResetter.classList.remove("has-custom-theme");
|
||||||
|
}
|
||||||
|
2
static/js/themeSwitcher.min.js
vendored
2
static/js/themeSwitcher.min.js
vendored
@ -1 +1 @@
|
|||||||
const themeSwitcher=document.querySelector(".theme-switcher");let currentTheme=localStorage.getItem("theme")||document.documentElement.getAttribute("data-theme");function setTheme(e,t=!1){document.documentElement.setAttribute("data-theme",e),currentTheme=e;let r="dark"===e?"true":"false";themeSwitcher.setAttribute("aria-pressed",r),t&&localStorage.setItem("theme",e);const h=new CustomEvent("themeChanged",{detail:{theme:e}});window.dispatchEvent(h)}function switchTheme(){setTheme("dark"===currentTheme?"light":"dark",!0)}themeSwitcher.addEventListener("click",switchTheme,!1),themeSwitcher.setAttribute("role","button");let togglePressed="dark"===currentTheme?"true":"false";themeSwitcher.setAttribute("aria-pressed",togglePressed),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",(e=>{setTheme(e.matches?"dark":"light")}));
|
const themeSwitcher=document.querySelector(".theme-switcher"),themeResetter=document.querySelector(".theme-resetter");let currentTheme=localStorage.getItem("theme")||document.documentElement.getAttribute("data-theme");function setTheme(e,t=!1){document.documentElement.setAttribute("data-theme",e);var r="dark"===(currentTheme=e)?"true":"false",r=(themeSwitcher.setAttribute("aria-pressed",r),t?(localStorage.setItem("theme",e),themeResetter.classList.add("has-custom-theme"),themeResetter.setAttribute("aria-hidden","false")):(localStorage.removeItem("theme"),themeResetter.classList.remove("has-custom-theme"),themeResetter.setAttribute("aria-hidden","true")),new CustomEvent("themeChanged",{detail:{theme:e}}));window.dispatchEvent(r)}function resetTheme(){setTheme(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")}function switchTheme(){setTheme("dark"===currentTheme?"light":"dark",!0)}themeSwitcher.addEventListener("click",switchTheme,!1),themeResetter.addEventListener("click",resetTheme,!1),themeSwitcher.setAttribute("role","button");let togglePressed="dark"===currentTheme?"true":"false";themeSwitcher.setAttribute("aria-pressed",togglePressed),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",e=>{setTheme(e.matches?"dark":"light")}),localStorage.getItem("theme")?themeResetter.classList.add("has-custom-theme"):themeResetter.classList.remove("has-custom-theme");
|
||||||
|
@ -15,4 +15,15 @@
|
|||||||
aria-label="{{ aria_label }}"
|
aria-label="{{ aria_label }}"
|
||||||
aria-pressed="false">
|
aria-pressed="false">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{%- set reset_str = macros_translate::translate(key='reset_mode', default='Reset mode to OS default', language_strings=language_strings) -%}
|
||||||
|
|
||||||
|
<div
|
||||||
|
title="{{ reset_str }}"
|
||||||
|
class="theme-resetter"
|
||||||
|
role="button"
|
||||||
|
aria-hidden="true"
|
||||||
|
aria-label="{{ reset_str }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user