forked from drowl87/hextra_mirror
feat: add option to set default theme and hide toggle button (#146)
resolves #135 Light / dark theme can be configured via: ```yaml theme: # light | dark | system default: system displayToggle: true ```
This commit is contained in:
parent
93cb788e52
commit
97e6945c04
@ -1,40 +1,51 @@
|
|||||||
// Dark theme toggle
|
// Light / Dark theme toggle
|
||||||
|
(function () {
|
||||||
|
const defaultTheme = '{{ site.Params.theme.default | default `system`}}'
|
||||||
|
|
||||||
const themeToggleButtons = document.querySelectorAll(".theme-toggle");
|
const themeToggleButtons = document.querySelectorAll(".theme-toggle");
|
||||||
|
|
||||||
// Change the icons inside the button based on previous settings
|
// Change the icons of the buttons based on previous settings or system theme
|
||||||
if (
|
if (
|
||||||
localStorage.getItem("color-theme") === "dark" ||
|
localStorage.getItem("color-theme") === "dark" ||
|
||||||
(!("color-theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches)
|
(!("color-theme" in localStorage) &&
|
||||||
) {
|
((window.matchMedia("(prefers-color-scheme: dark)").matches && defaultTheme === "system") || defaultTheme === "dark"))
|
||||||
themeToggleButtons.forEach((el) => el.dataset.theme = "dark");
|
) {
|
||||||
} else {
|
themeToggleButtons.forEach((el) => el.dataset.theme = "dark");
|
||||||
themeToggleButtons.forEach((el) => el.dataset.theme = "light");
|
} else {
|
||||||
}
|
themeToggleButtons.forEach((el) => el.dataset.theme = "light");
|
||||||
|
}
|
||||||
|
|
||||||
themeToggleButtons.forEach((el) => {
|
// Add click event handler to the buttons
|
||||||
el.addEventListener("click", function () {
|
themeToggleButtons.forEach((el) => {
|
||||||
if (localStorage.getItem("color-theme")) {
|
el.addEventListener("click", function () {
|
||||||
if (localStorage.getItem("color-theme") === "light") {
|
if (localStorage.getItem("color-theme")) {
|
||||||
document.documentElement.classList.add("dark");
|
if (localStorage.getItem("color-theme") === "light") {
|
||||||
document.documentElement.style.colorScheme = "dark";
|
setDarkTheme();
|
||||||
localStorage.setItem("color-theme", "dark");
|
localStorage.setItem("color-theme", "dark");
|
||||||
|
} else {
|
||||||
|
setLightTheme();
|
||||||
|
localStorage.setItem("color-theme", "light");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
document.documentElement.classList.remove("dark");
|
if (document.documentElement.classList.contains("dark")) {
|
||||||
document.documentElement.style.colorScheme = "light";
|
setLightTheme();
|
||||||
localStorage.setItem("color-theme", "light");
|
localStorage.setItem("color-theme", "light");
|
||||||
|
} else {
|
||||||
|
setDarkTheme();
|
||||||
|
localStorage.setItem("color-theme", "dark");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light";
|
||||||
if (document.documentElement.classList.contains("dark")) {
|
});
|
||||||
document.documentElement.classList.remove("dark");
|
|
||||||
document.documentElement.style.colorScheme = "light";
|
|
||||||
localStorage.setItem("color-theme", "light");
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.add("dark");
|
|
||||||
document.documentElement.style.colorScheme = "dark";
|
|
||||||
localStorage.setItem("color-theme", "dark");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light";
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
// Listen for system theme changes
|
||||||
|
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => {
|
||||||
|
if (defaultTheme === "system" && !("color-theme" in localStorage)) {
|
||||||
|
e.matches ? setDarkTheme() : setLightTheme();
|
||||||
|
themeToggleButtons.forEach((el) =>
|
||||||
|
el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
@ -5,7 +5,7 @@ weight: 2
|
|||||||
|
|
||||||
Hugo reads its configuration from `hugo.yaml` in the root of your Hugo site.
|
Hugo reads its configuration from `hugo.yaml` in the root of your Hugo site.
|
||||||
The config file is where you can configure all aspects of your site.
|
The config file is where you can configure all aspects of your site.
|
||||||
You can find the config file for this site in `exampleSite/hugo.yaml` as a good starting point.
|
Check out the config file for this site [`exampleSite/hugo.yaml`](https://github.com/imfing/hextra/blob/main/exampleSite/hugo.yaml) on GitHub to get a comprehensive idea of available settings and best practices.
|
||||||
|
|
||||||
<!--more-->
|
<!--more-->
|
||||||
|
|
||||||
@ -181,6 +181,26 @@ Include both `favicon.ico` and `favicon.svg` files in your project to ensure you
|
|||||||
While `favicon.ico` is generally for older browsers, `favicon.svg` is supported by modern ones. The optional `favicon-dark.svg` can be included for a tailored experience in dark mode.
|
While `favicon.ico` is generally for older browsers, `favicon.svg` is supported by modern ones. The optional `favicon-dark.svg` can be included for a tailored experience in dark mode.
|
||||||
Feel free to use tools like [favicon.io](https://favicon.io/) or [favycon](https://github.com/ruisaraiva19/favycon) to generate these icons.
|
Feel free to use tools like [favicon.io](https://favicon.io/) or [favycon](https://github.com/ruisaraiva19/favycon) to generate these icons.
|
||||||
|
|
||||||
|
### Theme Configuration
|
||||||
|
|
||||||
|
Use the `theme` setting to configure the default theme mode and toggle button, allowing visitors to switch between light or dark mode.
|
||||||
|
|
||||||
|
```yaml {filename="hugo.yaml"}
|
||||||
|
params:
|
||||||
|
theme:
|
||||||
|
# light | dark | system
|
||||||
|
default: system
|
||||||
|
displayToggle: true
|
||||||
|
```
|
||||||
|
|
||||||
|
Options for `theme.default`:
|
||||||
|
|
||||||
|
- `light` - always use light mode
|
||||||
|
- `dark` - always use dark mode
|
||||||
|
- `system` - sync with the operating system setting (default)
|
||||||
|
|
||||||
|
The `theme.displayToggle` parameter allows you to display a toggle button for changing themes.
|
||||||
|
When set to `true`, visitors can switch between light or dark mode, overriding the default setting.
|
||||||
|
|
||||||
### Page Width
|
### Page Width
|
||||||
|
|
||||||
@ -193,8 +213,7 @@ params:
|
|||||||
width: wide
|
width: wide
|
||||||
```
|
```
|
||||||
|
|
||||||
There are three available options: `full`, `wide`, and `normal`.
|
There are three available options: `full`, `wide`, and `normal`. By default, the page width is set to `normal`.
|
||||||
By default, the page width is set to `normal`.
|
|
||||||
|
|
||||||
Similarly, the width of the navbar and footer can be customized by the `params.navbar.width` and `params.footer.width` parameters.
|
Similarly, the width of the navbar and footer can be customized by the `params.navbar.width` and `params.footer.width` parameters.
|
||||||
|
|
||||||
@ -215,7 +234,8 @@ params:
|
|||||||
index: content
|
index: content
|
||||||
```
|
```
|
||||||
|
|
||||||
available options for `flexsearch.index`:
|
Options for `flexsearch.index`:
|
||||||
|
|
||||||
- `content` - full content of the page (default)
|
- `content` - full content of the page (default)
|
||||||
- `summary` - summary of the page, see [Hugo Content Summaries](https://gohugo.io/content-management/summaries/) for more details
|
- `summary` - summary of the page, see [Hugo Content Summaries](https://gohugo.io/content-management/summaries/) for more details
|
||||||
- `heading` - level 1 and level 2 headings
|
- `heading` - level 1 and level 2 headings
|
||||||
|
@ -109,6 +109,11 @@ params:
|
|||||||
# full (100%), wide (90rem), normal (1280px)
|
# full (100%), wide (90rem), normal (1280px)
|
||||||
width: normal
|
width: normal
|
||||||
|
|
||||||
|
theme:
|
||||||
|
# light | dark | system
|
||||||
|
default: system
|
||||||
|
displayToggle: true
|
||||||
|
|
||||||
footer:
|
footer:
|
||||||
displayCopyright: true
|
displayCopyright: true
|
||||||
displayPoweredBy: true
|
displayPoweredBy: true
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{{- $enableFooterSwitches := .Scratch.Get "enableFooterSwitches" | default false -}}
|
{{- $enableFooterSwitches := .Scratch.Get "enableFooterSwitches" | default false -}}
|
||||||
|
{{- $displayThemeToggle := site.Params.theme.displayToggle | default true -}}
|
||||||
|
|
||||||
{{- $copyright := (T "copyright") | default "© 2023 Hextra." -}}
|
{{- $copyright := (T "copyright") | default "© 2023 Hextra." -}}
|
||||||
|
|
||||||
@ -11,16 +12,19 @@
|
|||||||
{{ end -}}
|
{{ end -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
|
|
||||||
<footer class="hextra-footer bg-gray-100 pb-[env(safe-area-inset-bottom)] dark:bg-neutral-900 print:bg-transparent">
|
<footer class="hextra-footer bg-gray-100 pb-[env(safe-area-inset-bottom)] dark:bg-neutral-900 print:bg-transparent">
|
||||||
{{- if $enableFooterSwitches }}
|
{{- if $enableFooterSwitches -}}
|
||||||
<div class='mx-auto flex gap-2 py-2 px-4 {{ $footerWidth }}'>
|
<div class="mx-auto flex gap-2 py-2 px-4 {{ $footerWidth }}">
|
||||||
{{- partial "language-switch.html" (dict "context" .) -}}
|
{{- partial "language-switch.html" (dict "context" .) -}}
|
||||||
{{- partial "theme-toggle.html" -}}
|
{{- with $displayThemeToggle }}{{ partial "theme-toggle.html" }}{{ end -}}
|
||||||
</div>
|
</div>
|
||||||
{{ end -}}
|
{{- if or site.IsMultiLingual $displayThemeToggle -}}
|
||||||
<hr class="dark:border-neutral-800" />
|
<hr class="dark:border-neutral-800" />
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
<div
|
<div
|
||||||
class='{{ $footerWidth }} mx-auto flex justify-center py-12 pl-[max(env(safe-area-inset-left),1.5rem)] pr-[max(env(safe-area-inset-right),1.5rem)] text-gray-600 dark:text-gray-400 md:justify-start'
|
class="{{ $footerWidth }} mx-auto flex justify-center py-12 pl-[max(env(safe-area-inset-left),1.5rem)] pr-[max(env(safe-area-inset-right),1.5rem)] text-gray-600 dark:text-gray-400 md:justify-start"
|
||||||
>
|
>
|
||||||
<div class="flex w-full flex-col items-center sm:items-start">
|
<div class="flex w-full flex-col items-center sm:items-start">
|
||||||
{{- if (.Site.Params.footer.displayPoweredBy | default true) }}<div class="font-semibold">{{ template "theme-credit" . }}</div>{{ end }}
|
{{- if (.Site.Params.footer.displayPoweredBy | default true) }}<div class="font-semibold">{{ template "theme-credit" . }}</div>{{ end }}
|
||||||
|
@ -33,13 +33,25 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
/* Initialize light/dark mode */
|
/* Initialize light/dark mode */
|
||||||
if (localStorage.getItem("color-theme") === "dark" || (!("color-theme" in localStorage) && window.matchMedia("(prefers-color-scheme: dark)").matches)) {
|
const defaultTheme = '{{ site.Params.theme.default | default `system`}}';
|
||||||
|
|
||||||
|
const setDarkTheme = () => {
|
||||||
document.documentElement.classList.add("dark");
|
document.documentElement.classList.add("dark");
|
||||||
document.documentElement.style.colorScheme = "dark";
|
document.documentElement.style.colorScheme = "dark";
|
||||||
} else {
|
}
|
||||||
|
const setLightTheme = () => {
|
||||||
document.documentElement.classList.remove("dark");
|
document.documentElement.classList.remove("dark");
|
||||||
document.documentElement.style.colorScheme = "light";
|
document.documentElement.style.colorScheme = "light";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ("color-theme" in localStorage) {
|
||||||
|
localStorage.getItem("color-theme") === "dark" ? setDarkTheme() : setLightTheme();
|
||||||
|
} else {
|
||||||
|
defaultTheme === "dark" ? setDarkTheme() : setLightTheme();
|
||||||
|
if (defaultTheme === "system") {
|
||||||
|
window.matchMedia("(prefers-color-scheme: dark)").matches ? setDarkTheme() : setLightTheme();
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{{ partial "custom/head-end.html" . }}
|
{{ partial "custom/head-end.html" . }}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{{- $jsTheme := resources.Get "js/theme.js" -}}
|
{{- $jsTheme := resources.Get "js/theme.js" | resources.ExecuteAsTemplate "theme.js" . -}}
|
||||||
{{- $jsMenu := resources.Get "js/menu.js" -}}
|
{{- $jsMenu := resources.Get "js/menu.js" -}}
|
||||||
{{- $jsTabs := resources.Get "js/tabs.js" -}}
|
{{- $jsTabs := resources.Get "js/tabs.js" -}}
|
||||||
{{- $jsLang := resources.Get "js/lang.js" -}}
|
{{- $jsLang := resources.Get "js/lang.js" -}}
|
||||||
|
@ -34,17 +34,21 @@
|
|||||||
{{ end -}}
|
{{ end -}}
|
||||||
</div>
|
</div>
|
||||||
{{/* Hide theme switch when sidebar is disabled */}}
|
{{/* Hide theme switch when sidebar is disabled */}}
|
||||||
{{ $switchesClass := cond $disableSidebar "md:hidden" "" }}
|
{{ $switchesClass := cond $disableSidebar "md:hidden" "" -}}
|
||||||
<div class="{{ $switchesClass }} {{ with site.IsMultiLingual }}justify-end{{ end }} sticky bottom-0 bg-white dark:bg-dark mx-4 py-4 shadow-[0_-12px_16px_#fff] flex items-center gap-2 dark:border-neutral-800 dark:shadow-[0_-12px_16px_#111] contrast-more:border-neutral-400 contrast-more:shadow-none contrast-more:dark:shadow-none border-t" data-toggle-animation="show">
|
{{ $displayThemeToggle := (site.Params.theme.displayToggle | default true) -}}
|
||||||
{{- with site.IsMultiLingual }}
|
|
||||||
{{ partial "language-switch" (dict "context" $context "grow" true) }}
|
{{ if or site.IsMultiLingual $displayThemeToggle }}
|
||||||
{{ partial "theme-toggle" (dict "hideLabel" true) }}
|
<div class="{{ $switchesClass }} {{ with site.IsMultiLingual }}justify-end{{ end }} sticky bottom-0 bg-white dark:bg-dark mx-4 py-4 shadow-[0_-12px_16px_#fff] flex items-center gap-2 dark:border-neutral-800 dark:shadow-[0_-12px_16px_#111] contrast-more:border-neutral-400 contrast-more:shadow-none contrast-more:dark:shadow-none border-t" data-toggle-animation="show">
|
||||||
{{ else }}
|
{{- with site.IsMultiLingual -}}
|
||||||
<div class="flex grow flex-col">
|
{{- partial "language-switch" (dict "context" $context "grow" true) -}}
|
||||||
{{ partial "theme-toggle" }}
|
{{- with $displayThemeToggle }}{{ partial "theme-toggle" (dict "hideLabel" true) }}{{ end -}}
|
||||||
</div>
|
{{- else -}}
|
||||||
{{ end -}}
|
{{- with $displayThemeToggle -}}
|
||||||
</div>
|
<div class="flex grow flex-col">{{ partial "theme-toggle" }}</div>
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
{{- define "sidebar-main" -}}
|
{{- define "sidebar-main" -}}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user