✨ 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"
|
||||
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."
|
||||
|
||||
[taxonomies]
|
||||
@ -16,8 +16,8 @@ Aquest tema no requereix JavaScript obligatori. Opcionalment, pot carregar una q
|
||||
|
||||
## 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].
|
||||
|
||||
## Opcions que es poden sobreescriure de forma jeràrquica
|
||||
|
@ -1,7 +1,7 @@
|
||||
+++
|
||||
title = "Sin JavaScript obligatorio"
|
||||
date = 2023-01-06
|
||||
updated = 2023-09-01
|
||||
updated = 2023-10-06
|
||||
description = "JavaScript solo se utiliza cuando HTML y CSS no son suficientes."
|
||||
|
||||
[taxonomies]
|
||||
@ -16,8 +16,8 @@ Este tema no requiere JavaScript de manera obligatoria. Opcionalmente, puede car
|
||||
|
||||
## 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].
|
||||
|
||||
## Opciones que se pueden sobreescribir de forma jerárquica
|
||||
|
@ -1,7 +1,7 @@
|
||||
+++
|
||||
title = "No mandatory JavaScript"
|
||||
date = 2023-01-06
|
||||
updated = 2023-09-01
|
||||
updated = 2023-10-06
|
||||
description = "JavaScript is only used when HTML and CSS aren't enough."
|
||||
|
||||
[taxonomies]
|
||||
@ -16,7 +16,7 @@ This theme has no mandatory JavaScript. Optionally, it can load a minimal amount
|
||||
|
||||
## 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.
|
||||
|
||||
|
@ -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.
|
||||
dark = "obscur"
|
||||
light = "clar"
|
||||
reset_mode = "Restableix el mode als valors predeterminats del sistema"
|
||||
|
||||
# Post metadata.
|
||||
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.
|
||||
dark = "dunkel"
|
||||
light = "hell"
|
||||
reset_mode = "Modus auf Betriebssystemstandard zurücksetzen"
|
||||
|
||||
# Post metadata.
|
||||
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.
|
||||
dark = "dark"
|
||||
light = "light"
|
||||
reset_mode = "Reset mode to OS default"
|
||||
|
||||
# Post metadata.
|
||||
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.
|
||||
dark = "oscuro"
|
||||
light = "claro"
|
||||
reset_mode = "Restablecer modo a configuración predeterminada del SO"
|
||||
|
||||
# Post metadata.
|
||||
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.
|
||||
dark = "sombre"
|
||||
light = "clair"
|
||||
reset_mode = "Réinitialiser le mode aux paramètres par défaut du système"
|
||||
|
||||
# Post metadata.
|
||||
draft = "BROUILLON"
|
||||
|
@ -28,6 +28,7 @@ language_selection = "भाषा चयन"
|
||||
toggle_mode = "$MODE मोड में टॉगल करें" # $MODE will be replaced by a value (or both) below.
|
||||
dark = "अंधेरा"
|
||||
light = "रोशनी"
|
||||
reset_mode = "मोड को ओएस डिफ़ॉल्ट पर रीसेट करें"
|
||||
|
||||
# Post metadata.
|
||||
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.
|
||||
dark = "scuro"
|
||||
light = "chiaro"
|
||||
reset_mode = "Reimposta la modalità alle impostazioni predefinite del sistema operativo"
|
||||
|
||||
# Post metadata.
|
||||
draft = "BOZZA"
|
||||
|
@ -30,6 +30,7 @@ language_selection = "言語選択"
|
||||
toggle_mode = "$MODE モードに切り替え" # $MODE will be replaced by a value (or both) below.
|
||||
dark = "暗い"
|
||||
light = "明るい"
|
||||
reset_mode = "モードをOSデフォルトにリセット"
|
||||
|
||||
# Post metadata.
|
||||
draft = "ドラフト"
|
||||
|
@ -30,6 +30,7 @@ language_selection = "언어 선택"
|
||||
toggle_mode = "$MODE 모드로 전환" # $MODE will be replaced by a value (or both) below.
|
||||
dark = "어두운"
|
||||
light = "밝은"
|
||||
reset_mode = "모드를 OS 기본값으로 재설정"
|
||||
|
||||
# Post metadata.
|
||||
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.
|
||||
dark = "escuro"
|
||||
light = "claro"
|
||||
reset_mode = "Repor o modo para o padrão do SO"
|
||||
|
||||
# Post metadata.
|
||||
draft = "RASCUNHO"
|
||||
|
@ -26,6 +26,7 @@ language_selection = "Выбор языка"
|
||||
toggle_mode = "Переключить на режим $MODE" # $MODE will be replaced by a value (or both) below.
|
||||
dark = "тёмный"
|
||||
light = "светлый"
|
||||
reset_mode = "Сбросить режим к настройкам ОС по умолчанию"
|
||||
|
||||
# Post metadata.
|
||||
draft = "ЧЕРНОВИК"
|
||||
|
@ -30,6 +30,7 @@ language_selection = "Вибір мови"
|
||||
toggle_mode = "Перемкнути в режим $MODE" # $MODE will be replaced by a value (or both) below.
|
||||
dark = "темний"
|
||||
light = "світлий"
|
||||
reset_mode = "Скинути режим до типових параметрів ОС"
|
||||
|
||||
# Post metadata.
|
||||
draft = "ЧЕРНЕТКА"
|
||||
|
@ -24,8 +24,9 @@ all_posts = "所有文章"
|
||||
all_tags = "所有标签"
|
||||
language_selection = "语言选择" # 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.
|
||||
reset_mode = "重置为操作系统默认模式" # Machine translated.
|
||||
|
||||
# Post metadata.
|
||||
draft = "草稿"
|
||||
|
@ -26,6 +26,7 @@ language_selection = "語言選擇" # Machine translated.
|
||||
toggle_mode = "切換到$MODE模式" # $MODE will be replaced by a value (or both) below. Machine translated.
|
||||
dark = "暗" # Machine translated.
|
||||
light = "亮" # Machine translated.
|
||||
reset_mode = "重置為操作系統預設模式" # Machine translated.
|
||||
|
||||
# Post metadata.
|
||||
draft = "草稿"
|
||||
|
@ -11,3 +11,32 @@
|
||||
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 themeResetter = document.querySelector(".theme-resetter");
|
||||
|
||||
// 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');
|
||||
|
||||
// Function to set theme
|
||||
// Function to set theme.
|
||||
function setTheme(theme, saveToLocalStorage = false) {
|
||||
document.documentElement.setAttribute("data-theme", theme);
|
||||
currentTheme = theme;
|
||||
@ -13,6 +14,12 @@ function setTheme(theme, saveToLocalStorage = false) {
|
||||
|
||||
if (saveToLocalStorage) {
|
||||
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.
|
||||
@ -22,6 +29,12 @@ function setTheme(theme, saveToLocalStorage = false) {
|
||||
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 switchTheme() {
|
||||
// Set the new theme based on the current theme.
|
||||
@ -31,6 +44,8 @@ function switchTheme() {
|
||||
|
||||
// Initialize the theme switcher button.
|
||||
themeSwitcher.addEventListener("click", switchTheme, false);
|
||||
themeResetter.addEventListener("click", resetTheme, false);
|
||||
|
||||
themeSwitcher.setAttribute("role", "button");
|
||||
let togglePressed = currentTheme === "dark" ? "true" : "false";
|
||||
themeSwitcher.setAttribute("aria-pressed", togglePressed);
|
||||
@ -40,3 +55,9 @@ window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", e =
|
||||
const newTheme = e.matches ? "dark" : "light";
|
||||
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");
|
||||
|
@ -3,16 +3,27 @@
|
||||
{%- set toggle_str = macros_translate::translate(key='toggle_mode', default='Toggle $MODE mode', language_strings=language_strings) -%}
|
||||
{%- set dark_str = macros_translate::translate(key='dark', default='dark', language_strings=language_strings) -%}
|
||||
{%- set light_str = macros_translate::translate(key='light', default='light', language_strings=language_strings) -%}
|
||||
|
||||
|
||||
{%- set combined_mode_str = dark_str ~ "/" ~ light_str -%}
|
||||
{%- set title_label = toggle_str | replace(from="$MODE", to=combined_mode_str) -%}
|
||||
{%- set aria_label = toggle_str | replace(from="$MODE", to=dark_str) -%}
|
||||
|
||||
<div
|
||||
|
||||
<div
|
||||
title="{{ title_label }}"
|
||||
class="theme-switcher"
|
||||
role="button"
|
||||
aria-label="{{ aria_label }}"
|
||||
class="theme-switcher"
|
||||
role="button"
|
||||
aria-label="{{ aria_label }}"
|
||||
aria-pressed="false">
|
||||
</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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user