Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added default theme #960

Merged
merged 9 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions assets/scripts/features/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ if (process.env.FEATURE_DARKMODE === '1') {
import('./darkmode')
}

if (process.env.FEATURE_THEME === '1') {
import('./theme')
}

if (process.env.FEATURE_FLOWCHART === '1') {
import('./flowchart')
}
Expand Down
88 changes: 88 additions & 0 deletions assets/scripts/features/theme/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import * as params from '@params';
const PERSISTENCE_KEY = 'theme-scheme'

const themeOptions = params.theme || {}
const THEME_DARK = typeof themeOptions.dark === 'undefined' ? true : themeOptions.dark;
const THEME_LIGHT = typeof themeOptions.light === 'undefined' ? true : themeOptions.light;
const THEME_DEFAULT = typeof themeOptions.default === 'undefined' ? "system" : themeOptions.default;

window.addEventListener('load', async () => {
const menu = document.getElementById('themeMenu')
const $icon = document.getElementById('navbar-theme-icon-svg')
if (menu == null || $icon == null) return

const btns = menu.getElementsByTagName('a')
const iconMap = Array.from(btns).reduce((map, btn) => {
const $img = btn.getElementsByTagName('img')[0]
map[btn.dataset.scheme] = $img.src
return map
}, {})


function checkScheme(scheme) {
if (THEME_LIGHT === false) return "dark"
if (THEME_DARK === false) return "light"
return scheme
}

function loadScheme() {
return localStorage.getItem(PERSISTENCE_KEY) || loadDefaultScheme()
}

function loadDefaultScheme() {
return THEME_DEFAULT || "system"
}

function saveScheme(scheme) {
localStorage.setItem(PERSISTENCE_KEY, scheme)
}

function getPreferredColorScheme() {
const isDarkMode = window.matchMedia("(prefers-color-scheme: dark)").matches;
return isDarkMode ? "dark" : "light";
}

function setScheme(newScheme) {
let theme = newScheme
if (newScheme === 'system') {
theme = getPreferredColorScheme()
}
// set data-theme attribute on html tag
document.querySelector("html").dataset.theme = theme;

// update icon
$icon.src = iconMap[newScheme]

// save preference to local storage
saveScheme(newScheme)

setImages(theme)
}

const checkedScheme = checkScheme(loadScheme())
setScheme(checkedScheme)

Array.from(menu.getElementsByTagName('a')).forEach((btn) => {
btn.addEventListener('click', () => {
const { scheme } = btn.dataset
setScheme(scheme)
})
})
})

function setImages(newScheme) {
const els = Array.from(document.getElementsByClassName('logo-holder'));
for (const el of els) {
const light = el.querySelector('.light-logo');
const dark = el.querySelector('.dark-logo');

if (newScheme === "dark" && dark !== null) {
if (light !== null) light.style.display = 'none'
dark.style.display = 'inline'
}
else {
if (light !== null) light.style.display = 'inline'
if (dark !== null) dark.style.display = 'none'
}
}
}
14 changes: 12 additions & 2 deletions exampleSite/hugo.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,19 @@ params:
# Configure various features of this theme
features:

# Enable dark theme
darkMode:
# [Deprecated] Enable dark theme
# This is a deprecated setting, but has not been removed to maintain backward compatibility
# If `theme` is set, the `darkMode` setting will be discarded.
# darkMode:
# enable: true

# Configure theme color settings
theme:
enable: true
services:
light: true # enable light theme. default "true"
dark: true # enable dark theme. default "true"
default: system # can be either light, dark or system. default "system"

# Enable and configure portfolio
portfolio:
Expand Down
2 changes: 1 addition & 1 deletion layouts/_default/baseof.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<!--================= add analytics if enabled =========================-->
{{- partial "analytics.html" . -}}
<script>
theme = localStorage.getItem('darkmode:color-scheme') || 'system';
theme = localStorage.getItem('theme-scheme') || localStorage.getItem('darkmode:color-scheme') || 'light';
if (theme == 'system') {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
theme = 'dark';
Expand Down
2 changes: 1 addition & 1 deletion layouts/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<!--================= add analytics if enabled =========================-->
{{- partial "analytics.html" . -}}
<script>
theme = localStorage.getItem('darkmode:color-scheme') || 'system';
theme = localStorage.getItem('theme-scheme') || localStorage.getItem('darkmode:color-scheme') || 'light';
if (theme == 'system') {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
theme = 'dark';
Expand Down
15 changes: 13 additions & 2 deletions layouts/partials/helpers/get-esbuild-options.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,26 @@
# id: foo
# name: bar

# The `darkMode` feature
darkmode:
# [Deprecated] The `darkMode` feature
# This is a deprecated setting, but has not been removed to maintain backward compatibility
# If `theme` is set, the `darkMode` setting will be discarded.
darkMode:
enable: true

# The `theme` feature
theme:
enable: true
services:
light: true # enable light theme. default "true"
dark: true # enable dark theme. default "true"
default: system # can be either light, dark or system. default "system"

This helper will convert the above config into the following env vars:

* `FEATURE_ANALYTICS=1`
* `FEATURE_ANALYTICS_GOOGLE=1`
* `FEATURE_DARKMODE=1`
* `FEATURE_THEME=1`

In JS, you can use it like this:

Expand Down
2 changes: 1 addition & 1 deletion layouts/partials/navigators/navbar.html
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@
{{ if .IsTranslated }}
{{ partial "navigators/lang-selector.html" . }}
{{ end }}
{{ if site.Params.features.darkMode.enable }}
{{ if or site.Params.features.darkMode.enable site.Params.features.theme.enable }}
{{ partial "navigators/theme-selector.html" . }}
{{ end }}
</ul>
Expand Down
14 changes: 14 additions & 0 deletions layouts/partials/navigators/theme-selector.html
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
{{/* variables for enabling/disabling various features */}}
{{ $darkEnabled := true }}
{{ $lightEnabled := true }}
{{ if site.Params.features.theme.enable }}
{{ $darkEnabled = site.Params.features.theme.services.dark | default true }}
{{ $lightEnabled = site.Params.features.theme.services.light | default true }}
{{ end }}

<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="themeSelector" role="button"
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img id="navbar-theme-icon-svg" class="theme-icon" src="{{ "icons/moon-svgrepo-com.svg" | relURL }}" width=20 alt="Dark Theme">
</a>
<div id="themeMenu" class="dropdown-menu dropdown-menu-icons-only" aria-labelledby="themeSelector">
{{ if $lightEnabled }}
<a class="dropdown-item nav-link" href="#" data-scheme="light">
<img class="theme-icon" src="{{ "icons/sun-svgrepo-com.svg" | relURL }}" width=20 alt="Light Theme">
</a>
{{ end }}
{{ if $darkEnabled }}
<a class="dropdown-item nav-link" href="#" data-scheme="dark">
<img class="theme-icon" src="{{ "icons/moon-svgrepo-com.svg" | relURL }}" width=20 alt="Dark Theme">
</a>
{{ end }}
{{ if and $lightEnabled $darkEnabled }}
<a class="dropdown-item nav-link" href="#" data-scheme="system">
<img class="theme-icon" src="{{ "icons/computer-svgrepo-com.svg" | relURL }}" width=20 alt="System Theme">
</a>
{{ end }}
</div>
</li>
Loading