I am experimenting with bslib
's dark/light mode feature. I would like to replot a base R graphic depending on the dark/light mode. In particular, I want to set the fg
and bg
options to par()
.
A quick search brought up the functions bs_current_theme
and bs_get_variables
:
current_theme <- bslib::bs_current_theme()
bg <- bslib::bs_get_variables(current_theme, "body-bg")[["body-bg"]]
However, the value of bg
seems not to change after toggle_dark_mode()
is called. Here is an example app that prints bg
every time the dark/light mode button is pressed:
ui <- bslib::page_navbar(
title = "Dark Mode Demo",
theme = bslib::bs_theme(version=5),
bslib::nav_panel(
title = "Base Graphics",
bslib::card(
bslib::card_header("Mosaic"),
shiny::plotOutput("base_mosaic")
)
),
bslib::nav_spacer(),
bslib::nav_item(
bslib::input_dark_mode(id = "theme_toggle", mode = "light")
)
)
server <- function(input, output, session) {
# dark / light mode
shiny::observeEvent(input$theme_toggle, {
bslib::toggle_dark_mode(mode=input$theme_toggle)
current_theme <- bslib::bs_current_theme()
message("bg=", bslib::bs_get_variables(current_theme, "body-bg")[["body-bg"]])
par(bg = bslib::bs_get_variables(current_theme, "body-bg")[["body-bg"]])
})
output$base_mosaic <- shiny::renderPlot({
plot(1:10)
})
}
shiny::shinyApp(ui, server)
What is the best way to determine the current background and foreground (=text) color in bslib
?
Here is a possibility using a small custom message handler: It gets the current value of the Bootstrap variable --bs-body-bg
and sends it to Shiny:
library(shiny)
library(bslib)
ui <- page_navbar(
tags$head(
tags$script("
Shiny.addCustomMessageHandler('get_bg', function(value) {
var bg = getComputedStyle(document.body).getPropertyValue('--bs-body-bg');
Shiny.setInputValue('current_bg', {bg});
});
")
),
title = "Dark Mode Demo",
theme = bs_theme(version=5),
nav_panel(
title = "Base Graphics",
card(
card_header("Mosaic"),
plotOutput("base_mosaic")
)
),
nav_spacer(),
nav_item(
input_dark_mode(id = "theme_toggle", mode = "light")
)
)
server <- function(input, output, session) {
# dark / light mode
observeEvent(input$theme_toggle, {
toggle_dark_mode(mode=input$theme_toggle)
session$sendCustomMessage("get_bg", "")
req(input$current_bg)
message("bg=", input$current_bg)
})
output$base_mosaic <- renderPlot({
par(bg = input$current_bg)
plot(1:10)
})
}
shinyApp(ui, server)