-
DescriptionCurrently, both the Quarto website and Shinylive support dark mode. But when the website switches to dark mode, the Shinylive is not automatically switched. Are there any suggestions? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 12 replies
-
I think this would be a shinylive question so that CSS for shinylive does respect the dark / light mode in Quarto. Does shinlylive include a light / dark CSS ? I don't know enough about this extension. Did you ask the question on shinylive side ? @schloerke @gadenbuie do you have some insight on how dark mode works for shinylive component ? |
Beta Was this translation helpful? Give feedback.
-
For anyone who is interested, here is how I solved them problem (an interactive guide is available in my blog post): (Updated following @gadenbuie's suggestions) First, in the Quarto Website Page, we need to add a JavaScript (script?) to communicate with the ShinyLive app, which is in iframe. The adding is done by: include-after-body:
text: |
<script type="application/javascript" src="js/light-dark.js"></script> The actual light-dark.js file is inspired by @mcanouil 's code from his blog and needs to contain: const DarkEvent = new CustomEvent("quarto-color-mode", { detail: { mode: "dark" }}); // add new events
const LightEvent = new CustomEvent("quarto-color-mode", { detail: { mode: "light" }});
function updateAppTheme() { // dispatch events when theme needs updating
var bodyClass = window.document.body.classList;
if (bodyClass.contains('quarto-light')) {
window.dispatchEvent(LightEvent);
} else if (bodyClass.contains('quarto-dark')) {
window.dispatchEvent(DarkEvent);
}
}
var observer = new MutationObserver(function(mutations) { // listen for theme changes
mutations.forEach(function(mutation) {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
updateAppTheme();
}
});
});
observer.observe(window.document.body, { // enable observer
attributes: true
});
window.onmessage = function(e) { // update theme when receives querry
if (e.data == 'ShinyColorQuery') {
updateAppTheme();
}
}; Back to the ShinyLive app, it also needs to add a JS script to communicate with the parent page. A minimal working ShinyLive app code looks like this: #| standalone: true
## file: app.py
from shiny import *
from pathlib import Path
app_ui = ui.page_fluid(
"This is a Shinylive app with dark theme synced with Quarto", # other ui inputs that you like
ui.head_content(ui.include_js(Path(__file__).parent / "light-dark.js")),
)
app = App(app_ui, None)
## file: requirements.txt
## file: light-dark.js
window.parent.addEventListener("quarto-color-mode", function(event) {
// Shiny.setInputValue('quarto_mode', event.detail.mode);
document.documentElement.dataset.bsTheme = event.detail.mode;
if (event.detail.mode === "dark") {
document.documentElement.style.setProperty('--bs-body-bg', "#16242f"); // custom dark background color
} else if (event.detail.mode === "light") {
document.documentElement.style.setProperty('--bs-body-bg', "#f9fffe"); // custom light background color
}
})
window.parent.postMessage('ShinyColorQuery', '*'); // request Quarto theme color when Shinyapp is loaded |
Beta Was this translation helpful? Give feedback.
I think this would be a shinylive question so that CSS for shinylive does respect the dark / light mode in Quarto.
Does shinlylive include a light / dark CSS ? I don't know enough about this extension. Did you ask the question on shinylive side ?
@schloerke @gadenbuie do you have some insight on how dark mode works for shinylive component ?