-
-
Notifications
You must be signed in to change notification settings - Fork 302
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
Dynamic theme changing available? #336
Comments
Yes, you can send a |
function changeGiscusTheme () {
const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light'
function sendMessage(message) {
const iframe = document.querySelector('iframe.giscus-frame');
if (!iframe) return;
iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
}
sendMessage({
setConfig: {
theme: theme
}
});
} call the |
I tried this and it works, however, it is only possible to set the theme at runtime, is there a way to set |
Well I suppose instead of adding the provided <script>
let giscusTheme = localStorage.getItem("giscus-theme");
let giscusAttributes = {
"src": "https://giscus.app/client.js",
"data-repo": "[ENTER REPO HERE]",
"data-repo-id": "[ENTER REPO ID HERE]",
"data-category": "[ENTER CATEGORY NAME HERE]",
"data-category-id": "[ENTER CATEGORY ID HERE]",
"data-mapping": "pathname",
"data-reactions-enabled": "1",
"data-emit-metadata": "0",
"data-theme": giscusTheme,
"data-lang": "en",
"crossorigin": "anonymous",
"async": "",
};
let giscusScript = document.createElement("script");
Object.entries(giscusAttributes).forEach(([key, value]) => giscusScript.setAttribute(key, value));
document.body.appendChild(giscusScript);
</script> |
Nice, it's working now! |
Thank you for your code. I did this at the end: function changeGiscusTheme () {
let modeToggle = new ModeToggle();
const theme = modeToggle.mode === 'dark' ? 'dark' : 'light'
function sendMessage(message) {
const iframe = document.querySelector('iframe.giscus-frame');
if (!iframe) return;
iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
}
sendMessage({
setConfig: {
theme: theme
}
});
}
const modeToggle = document.getElementsByClassName("mode-toggle")[0];
if (typeof modeToggle !== "undefined") {
modeToggle.addEventListener('click', changeGiscusTheme);
} You can see my blog here. |
I tried this and I found that it became completely transparent, but did not automatically change the theme. |
Hi! Your results are great! What is the complete code? Where should I put it? |
Here's an example |
Thanks for your help! So, what about keeping the default code of giscus in post.html? |
Hello. I'm trying to follow the above but can't get it to work. I'm quite a newbie with HTML/JavaScript, so may be missing something that hopefully will be obvious to someone on this thread. I'm building a website with Quarto. I've set up a minimal example at https://github.com/EllaKaye/quarto-test and deployed it at https://serene-clafoutis-76cc16.netlify.app/ with an example post with giscus enabled. I've got a script included in the header:
which is the solution by @marcosruiz above, but swapping However, it's still not working for me, and that's as far as my HTML/JS knowledge goes on this. Any assistance would be much appreciated. Thank you! |
Hey @EllaKaye, I don't think you can use that solution as-is because your site's setup doesn't have the You can try this instead: function changeGiscusTheme() {
const theme = document.body.classList.contains('quarto-dark') ? 'dark' : 'light';
function sendMessage(message) {
const iframe = document.querySelector('iframe.giscus-frame');
if (!iframe) return;
iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
}
sendMessage({
setConfig: {
theme: theme,
},
});
}
const toggle = document.querySelector('.quarto-color-scheme-toggle');
if (toggle) {
toggle.addEventListener('click', changeGiscusTheme);
} |
Hi @laymonage Thanks for digging into this and getting back to me so quickly with a proposed solution 😄. I'm afraid, though, that it still isn't working for me. I think (but I'm not sure) that it may be something to do with the order that scripts are getting loaded into the header with Quarto. At the moment, I have the following in my yaml:
When I then view the page source, the script in I've pushed these changes to the https://github.com/EllaKaye/quarto-test repo and the corresponding https://serene-clafoutis-76cc16.netlify.app/ site. Thinking that I may need to have the script embedding giscus before the script for toggling theme, I also tried removing the yaml for generating the embedding script and instead used the configuration from https://giscus.app/ and put the script generated there directly in It's just a conjecture. Does it sound plausible? If not, can you think of any other issue that might be preventing the script from working? Thank you for helping me with this. |
@EllaKaye Does this work? function changeGiscusTheme() {
const theme = document.body.classList.contains('quarto-dark') ? 'dark' : 'light';
function sendMessage(message) {
const iframe = document.querySelector('iframe.giscus-frame');
if (!iframe) return;
iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
}
sendMessage({
setConfig: {
theme: theme,
},
});
}
document.addEventListener('DOMContentLoaded', function () {
const toggle = document.querySelector('.quarto-color-scheme-toggle');
if (toggle) {
toggle.addEventListener('click', changeGiscusTheme);
}
}); |
Yes! That does the trick 😄 Thank you so much for solving this (and helping me learn more JavaScript along the way!) |
Oh, actually, there is one thing that needs tweaking in the function. If I open a post in light mode, the comment section has the light theme, and toggles back and forth between light and dark, as it should. However, if I open a post in dark mode, the comment section starts off light. If I toggle to light mode, it stays light, then goes dark when I toggle back to dark mode, and toggles correctly from there on in. Is there a way to tweak the function so that the comment box always starts in the right mode? Thanks! |
You can follow the code described in #336 (comment). It hasn't been updated to add some new options though (e.g. You can put it as part of the previous script, e.g. function getGiscusTheme() {
const quartoTheme = localStorage.getItem("quarto-color-scheme");
const giscusTheme = quartoTheme === "alternate" ? "dark" : "light";
return giscusTheme;
}
function setGiscusTheme() {
function sendMessage(message) {
const iframe = document.querySelector('iframe.giscus-frame');
if (!iframe) return;
iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
}
sendMessage({
setConfig: {
theme: getGiscusTheme(),
},
});
}
document.addEventListener('DOMContentLoaded', function () {
const giscusAttributes = {
"src": "https://giscus.app/client.js",
"data-repo": "[ENTER REPO HERE]",
"data-repo-id": "[ENTER REPO ID HERE]",
"data-category": "[ENTER CATEGORY NAME HERE]",
"data-category-id": "[ENTER CATEGORY ID HERE]",
"data-mapping": "pathname",
"data-strict": "0",
"data-reactions-enabled": "1",
"data-emit-metadata": "0",
"data-input-position": "top",
"data-theme": getGiscusTheme(),
"data-lang": "en",
"crossorigin": "anonymous",
"async": "",
};
// Dynamically create script tag
const giscusScript = document.createElement("script");
Object.entries(giscusAttributes).forEach(([key, value]) => giscusScript.setAttribute(key, value));
document.body.appendChild(giscusScript);
// Update giscus theme when theme switcher is clicked
const toggle = document.querySelector('.quarto-color-scheme-toggle');
if (toggle) {
toggle.addEventListener('click', setGiscusTheme);
}
}); Note that since the script tag is created dynamically and appended to the end of the |
@laymonage you are truly an open source hero for the quality of your software as well as the helpfulness and speed of your responses to issues/questions 😄 When my website goes live and I blog about implementing this feature, I will give you a big shout out and lots of credit. Your above solution works perfectly for my test repo/site as it was when I posted my original question. There was a little bit more figuring out for me to do in the more complex situation, as per my full website, where Quarto generates an appendix for each post, in order to ensure that the comments box appeared after the appendix. I have updated my test repo and deployed site to include this. For any Quarto users stumbling across this thread later, this is the full solution:
If you want the comments to come below the blog post but above the appendix, remove the I think that's it now! Thank you again so much for all your help with this. |
Glad to have helped, and thanks for writing down your solution! I'll try to make a compilation of guides/solutions based on people's different website setups. |
I found a solution using media queries so the user can just set their browser's light/dark mode preference in one spot instead of a toggle on every website: (function() {
var dmmq = window.matchMedia('(prefers-color-scheme: dark)');
var giscusFrame;
function updateGiscus() {
if (!giscusFrame) giscusFrame = document.querySelector('iframe.giscus-frame');
if (dmmq.matches) {
// Dark theme
giscusFrame.contentWindow.postMessage({ giscus: { setConfig: { theme: 'dark' } } }, 'https://giscus.app');
} else {
// Light theme
giscusFrame.contentWindow.postMessage({ giscus: { setConfig: { theme: 'light' } } }, 'https://giscus.app');
}
}
setTimeout(updateGiscus, 1000); // leave time for giscus to load
dmmq.addEventListener('change', updateGiscus);
})(); |
### Prerequisites Put an `x` into the box(es) that apply: - [ ] This pull request fixes a bug. - [x] This pull request adds a feature. - [ ] This pull request introduces breaking change. ### Description Adds support for [Giscus](https://giscus.app) as an alternative to [Utterances](https://utteranc.es), for a more extensive comment system based on GitHub Discussions (supports threading) rather than GitHub Issues. I've also implemented dynamic theme changing depending on the site theme set, similar to Utterances. Giscus inherits the same existing theme names as it uses the `dark` and `light` values, unlike Utterances which uses `github-dark` and `github-light`. This was helpful for dynamic theme changing as I'm not too experienced with JavaScript: giscus/giscus#336. I was also wondering if empty attributes in the script tag in `giscus.html` should be avoided (by not loading the params if not set), since not all are required. As for defaults, the sames ones as on [giscus](https://giscus.app) are used. Let me know if any optimizations are needed. ### Issues Resolved Closes #747. ### Checklist Put an `x` into the box(es) that apply: #### General - [x] Describe what changes are being made - [x] Explain why and how the changes were necessary and implemented respectively - [x] Reference issue with `#<ISSUE_NO>` if applicable #### Resources - [ ] If you have changed any SCSS code, run `make release` to regenerate all CSS files #### Contributors - [x] Add yourself to `CONTRIBUTORS.md` if you aren't on it already
work for me. thanks 😄 here |
Thanks to all who contributed to this thread! 👍 I used it (along with some excellent advice I received elsewhere) to come up with the following for using giscus on my Hugo-based site’s repo: https://github.com/brycewray/hugo-site/blob/main/layouts/partials/comments-giscus.html (Related post: https://www.brycewray.com/posts/2023/08/making-giscus-less-gabby/) |
I know that the issue has been closed, but when I am reading the doc I realized that I can use the const globalColorMode = 'light'; // or you get it from some function/global state
// https://github.com/giscus/giscus/issues/336#issuecomment-1007922777
function changeGiscusTheme(theme) {
function sendMessage(message) {
const iframe = document.querySelector('iframe.giscus-frame');
if (!iframe) return;
iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
}
sendMessage({
setConfig: {
theme: theme
}
});
}
// set giscus theme after giscus has been loaded
function handleGiscusMessage(event) {
if (event.origin !== 'https://giscus.app') return;
if (!(typeof event.data === 'object' && event.data.giscus)) return;
// const giscusData = event.data.giscus;
changeGiscusTheme(globalColorMode);
window.removeEventListener('message', handleMessage);
}
window.addEventListener('message', handleGiscusMessage); |
I am using #nextjs with tailwindcss. I just had to do this to get the dark mode toggle support working.
|
I'm newbie to web development, @marcosruiz could you share your complete code? I used the methods already shown here and I couldn't make it work on my blog. Edit: For me works with the PR code: https://github.com/lxndrblz/anatole/pull/448/files Thank you. |
It's great. But it still has a problem. This way does not work while refreshing the page. the theme will reset to light mode. |
can i this in vitepress? how? where? my repo |
Hello, is dynamic theme changing available? Because, I want this to change the theme automatically, according to the website.
The text was updated successfully, but these errors were encountered: