You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I found a very interesting solution to allow the theme toggle button to switch between light and dark mode images in a very simple code. While this works beautifully in markdown files, for the specific hextra cards and feature-cards, etc. it will not allow me to integrate it or choose a dark image which is a bummer.
2024-06-20.20-29-42.mp4
Let me show you what I did for the markdown:
You will need to input the figure-dynamic-toggle.html in your layouts/partials/shortcodes:
<figure{{ with .Get "class" }} class="{{ . }}"{{ end }}>
{{- if .Get "link" -}}
<a href="{{ .Get "link" }}"{{ with .Get "target" }} target="{{ . }}"{{ end }}{{ with .Get "rel" }} rel="{{ . }}"{{ end }}>
{{- end -}}
<picture class="theme-toggle-picture">
<source srcset="{{ .Get "dark-src" }}"
{{- if or (.Get "alt") (.Get "caption") }}
alt="{{ with .Get "alt" }}{{ . }}{{ else }}{{ .Get "caption" | markdownify | plainify }}{{ end }}"
{{- end -}}
{{- with .Get "width" }} width="{{ . }}"{{ end -}}
{{- with .Get "height" }} height="{{ . }}"{{ end -}}
media="(prefers-color-scheme: dark)">
<img src="{{ .Get "light-src" }}"
{{- if or (.Get "alt") (.Get "caption") }}
alt="{{ with .Get "alt" }}{{ . }}{{ else }}{{ .Get "caption" | markdownify | plainify }}{{ end }}"
{{- end -}}
{{- with .Get "width" }} width="{{ . }}"{{ end -}}
{{- with .Get "height" }} height="{{ . }}"{{ end -}}>
</picture>
{{- if .Get "link" }}</a>{{ end -}}
{{- if or (or (.Get "title") (.Get "caption")) (.Get "attr") -}}
<figcaption>
{{ with (.Get "title") -}}
<h4>{{ . }}</h4>
{{- end -}}
{{- if or (.Get "caption") (.Get "attr") -}}<p>
{{- .Get "caption" | markdownify -}}
{{- $attrlink := .Get "attrlink" }}
{{- $attr := .Get "attr" | htmlEscape }}
{{- if $attrlink -}}
{{- printf "[%s](%s)" $attr $attrlink | markdownify -}}
{{- else -}}
{{- $attr | markdownify -}}
{{- end }}
{{- end }}
</figcaption>
{{- end }}
</figure>
You will need to create a assets/js and an assets/css
a. In your assets/js, you will need 2 to create/update 2 files. A theme.js and an updateSourceMedia.js
updateSourceMedia.js
/**
* Make <picture> <source> elements with media="(prefers-color-scheme:)"
* respect custom theme preference overrides.
* Otherwise the `media` preference will only respond to the OS-level setting
*/
const updateSourceMedia = (colorPreference) => {
const pictures = document.querySelectorAll('picture');
pictures.forEach((picture) => {
const sources = picture.querySelectorAll(`
source[media*="prefers-color-scheme"],
source[data-media*="prefers-color-scheme"]
`);
sources.forEach((source) => {
// Preserve the source `media` as a data-attribute
// to be able to switch between preferences
if (source?.media.includes('prefers-color-scheme')) {
source.dataset.media = source.media;
}
// If the source element `media` target is the `preference`,
// override it to 'all' to show
// or set it to 'none' to hide
if (source?.dataset.media.includes(colorPreference)) {
source.media = 'all';
} else if (source) {
source.media = 'none';
}
});
});
};
// Hooking into the theme toggle logic
document.addEventListener('DOMContentLoaded', () => {
const defaultTheme = '{{ .Site.Params.theme.default | default "system" }}';
const themeToggleButtons = document.querySelectorAll(".theme-toggle");
const updateTheme = (theme) => {
document.documentElement.setAttribute('data-theme', theme);
updateSourceMedia(theme);
};
const currentTheme = localStorage.getItem("color-theme") ||
((window.matchMedia("(prefers-color-scheme: dark)").matches && defaultTheme === "system") ? "dark" : "light");
updateTheme(currentTheme);
themeToggleButtons.forEach((el) => {
el.addEventListener("click", function () {
const newTheme = (document.documentElement.getAttribute('data-theme') === 'dark') ? 'light' : 'dark';
localStorage.setItem("color-theme", newTheme);
updateTheme(newTheme);
});
});
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (e) => {
if (defaultTheme === "system" && !("color-theme" in localStorage)) {
const newTheme = e.matches ? 'dark' : 'light';
updateTheme(newTheme);
}
});
});
theme.js
// Light / Dark theme toggle
(function () {
const defaultTheme = '{{ site.Params.theme.default | default `system`}}';
const themeToggleButtons = document.querySelectorAll(".theme-toggle");
// Function to update image sources based on theme
const updateSourceMedia = (colorPreference) => {
const pictures = document.querySelectorAll('.theme-toggle-picture');
pictures.forEach((picture) => {
const sources = picture.querySelectorAll('source');
sources.forEach((source) => {
if (source.media.includes('prefers-color-scheme')) {
source.dataset.media = source.media;
}
if (source.dataset.media.includes(colorPreference)) {
source.media = 'all';
} else {
source.media = 'none';
}
});
});
};
// Function to set dark theme
const setDarkTheme = () => {
document.documentElement.classList.add("dark");
document.documentElement.setAttribute('data-theme', 'dark');
updateSourceMedia('dark');
};
// Function to set light theme
const setLightTheme = () => {
document.documentElement.classList.remove("dark");
document.documentElement.setAttribute('data-theme', 'light');
updateSourceMedia('light');
};
// Set initial theme based on saved preference or system setting
const currentTheme = localStorage.getItem("color-theme") ||
((window.matchMedia("(prefers-color-scheme: dark)").matches && defaultTheme === "system") ? "dark" : "light");
if (currentTheme === "dark") {
setDarkTheme();
} else {
setLightTheme();
}
themeToggleButtons.forEach((el) => el.dataset.theme = currentTheme);
// Add click event handler to the buttons
themeToggleButtons.forEach((el) => {
el.addEventListener("click", function () {
if (document.documentElement.classList.contains("dark")) {
setLightTheme();
localStorage.setItem("color-theme", 'light');
} else {
setDarkTheme();
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)) {
if (e.matches) {
setDarkTheme();
} else {
setLightTheme();
}
themeToggleButtons.forEach((el) => el.dataset.theme = document.documentElement.classList.contains("dark") ? "dark" : "light");
}
});
})();
Once you have done this, proceed to your markdown, for me, I'm gonna test it in my about me page. So, this works in either _index.md or index.md files.
Paste this in your markdown
{{<figure-dynamic-toggle
dark-src="DMPMechanismQ1Dark.png"
light-src="DMPMechanismQ1Light.png"
alt="Description of the image"
caption="This image changes based on the theme."
link="/..."
>}}
Xin and the other Hextra users, I'm asking if you can kindly look into using this code and allowing your hextra cards, feature-cards and other dynamic image based content used my figure-dynamic-toggle code its a very easy to switch. The only problem is every time I try and integrate it, I failed lol.
Thank you all for leaving your repos open for me to peruse and thank you for making this open source
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Hi Xin and the Hextra Team and Users
I found a very interesting solution to allow the theme toggle button to switch between light and dark mode images in a very simple code. While this works beautifully in markdown files, for the specific hextra cards and feature-cards, etc. it will not allow me to integrate it or choose a dark image which is a bummer.
2024-06-20.20-29-42.mp4
Let me show you what I did for the markdown:
a. In your assets/js, you will need 2 to create/update 2 files. A theme.js and an updateSourceMedia.js
updateSourceMedia.js
theme.js
See files for this:
b. You next need a styles.css in your assets/css
assets.css
Paste this in your markdown
Xin and the other Hextra users, I'm asking if you can kindly look into using this code and allowing your hextra cards, feature-cards and other dynamic image based content used my figure-dynamic-toggle code its a very easy to switch. The only problem is every time I try and integrate it, I failed lol.
Thank you all for leaving your repos open for me to peruse and thank you for making this open source
Beta Was this translation helpful? Give feedback.
All reactions